gpt4 book ai didi

c# - 创建用于测试的 DirectoryEntry 实例

转载 作者:太空狗 更新时间:2023-10-29 23:34:19 26 4
gpt4 key购买 nike

我正在尝试创建 DirectoryEntry 的实例,以便我可以使用它来测试一些将传递给 DirectoryEntry 的代码。然而,尽管进行了很多尝试,我还是找不到一种方法来实例化 DE 并初始化它的 PropertyCollection。

我有以下代码,这些代码是从 another answer on SO 中提取和修改的除了 SearchResult 对象之外,它正在执行相同的过程。似乎 Add 方法已被完全禁用,我找不到调用 PropertyCollection 上的构造函数来传入某些属性的方法。

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"});

我希望我错过了一些东西,因为我对在愤怒中使用反射还很陌生。

最佳答案

我不熟悉 DirectoryEntry 本身,但我非常喜欢用于测试的适配器模式。不得不做这样的事情很烦人,但代码本身很简单,可以将类放在项目文件夹中以将它们隐藏在主项目之外。

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

文件信息适配器:

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; } }
}

关于c# - 创建用于测试的 DirectoryEntry 实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5966161/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com