本文介绍了在测试使用创建的DirectoryEntry的实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图创建一个DirectoryEntry的实例,这样我可以用它来测试将传递一个DirectoryEntry一些code。然而,尽管很多努力,我不能找到一个方法来实例化一个DE和初始化它的PropertyCollection。

I'm attempting to create an instance of a DirectoryEntry so that I can use this to test some code that will be passed a DirectoryEntry. However, despite a lot of trying I can't find a way to instantiate a DE and initialize it's PropertyCollection.

我有以下的code,将其溶解,并从another回答SO 这是做同样的过程,但对于信息搜索结果的对象。看来,Add方法已经完全禁用,我无法找到一个方法来调用PropertyCollection一个构造函数来传递一些属性。

I have the following code which was taken and modified from another answer on SO that was doing the same process but for the SearchResult object. It seems that the Add method has been completely disabled and I can't find a way to call a constructor on PropertyCollection to pass in some properties.

using System.Collections;
using System.DirectoryServices;
using System.Globalization;
using System.Reflection;
using System.Runtime.Serialization;

public static class DirectoryEntryFactory
{
    const BindingFlags nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
    const BindingFlags publicInstance = BindingFlags.Public | BindingFlags.Instance;

    public static DirectoryEntry Construct<T>(T anonInstance)
    {
        var e = GetUninitializedObject<DirectoryEntry>();

        SetPropertiesField(e);

        var dictionary = (IDictionary)e.Properties;
        var type = typeof(T);
        var propertyInfos = type.GetProperties(publicInstance);

        foreach (var propertyInfo in propertyInfos)
        {
            var value = propertyInfo.GetValue(anonInstance, null);
            var valueCollection = GetUninitializedObject<PropertyValueCollection>();
            var innerList = GetInnerList(valueCollection);
            innerList.Add(value);

            var lowerKey = propertyInfo.Name.ToLower(CultureInfo.InvariantCulture);

            // These both throw exceptions saying you can't add to a PropertyCollection
            //(typeof(PropertyCollection)).InvokeMember("System.Collections.IDictionary.Add", nonPublicInstance | BindingFlags.InvokeMethod, null, dictionary, new object[] { propertyInfo.Name, value });
            //dictionary.Add(lowerKey, propertyCollection);
        }

        return e;
    }

    private static ArrayList GetInnerList(object propertyCollection)
    {
        var propertyInfo = typeof(PropertyValueCollection).GetProperty("InnerList", nonPublicInstance);
        return (ArrayList)propertyInfo.GetValue(propertyCollection, null);
    }

    private static void SetPropertiesField(DirectoryEntry e)
    {
        var propertiesField = typeof(DirectoryEntry).GetField("propertyCollection", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        propertiesField.SetValue(e, GetUninitializedObject<PropertyCollection>());
    }

    private static T GetUninitializedObject<T>()
    {
        return (T)FormatterServices.GetUninitializedObject(typeof(T));
    }
}

用法旨在是

DirectoryEntry e = DirectoryEntryFactory.Construct(new { attr1 = "Hello", attr2 = "World"});

我希望我已经错过了一些东西,因为我是pretty的新愤怒地使用反射。

I'm hoping I've missed something as I'm pretty new to using reflection in anger.

推荐答案

我不熟悉的DirectoryEntry本身,但我的测试适配器模式的忠实粉丝。这是你必须做这样的事情的烦恼,但C本身的$ C $是微不足道的类可以被放置在项目文件夹来隐藏他们远离你的主要项目。

I'm not familiar with DirectoryEntry itself, but I'm a big fan of the Adapter pattern for testing. It is an annoyance that you would have to do such a thing, but the code itself is trivial and the classes can be placed in a project folder to hide them away from your main project.

例如,我有一个FileInfoAdapter和DirectoryInfoAdapter的包装那些接触到文件系统的类。

For example, I have a FileInfoAdapter and DirectoryInfoAdapter that wrap those classes that touch the filesystem.

FileInfoAdapter:

FileInfoAdapter:

public class FileInfoAdapter : IFileInfo
{
    private readonly FileSystemInfo _fi;

    public FileInfoAdapter(string fileName)
        : this(new FileInfo(fileName))
    { }

    public FileInfoAdapter(FileSystemInfo fi)
    {
        _fi = fi;
    }

    public string Name { get { return _fi.Name; } }
    public string FullName { get { return _fi.FullName; } }
    public bool Exists { get { return _fi.Exists; } }
}

这篇关于在测试使用创建的DirectoryEntry的实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 01:23