gpt4 book ai didi

c# - 通过反射获取接口(interface)类型的构造函数,有没有比遍历类型更好的方法?

转载 作者:太空宇宙 更新时间:2023-11-03 17:46:21 25 4
gpt4 key购买 nike

我写了一个泛型:IDirectorySource<T> where T : IDirectoryEntry ,我用来通过我的接口(interface)对象管理 Active Directory 条目:IGroup , IOrganizationalUnit , IUser .

这样我就可以编写以下内容:

IDirectorySource<IGroup> groups = new DirectorySource<IGroup>(); // Where IGroup implements `IDirectoryEntry`, of course.`

foreach (IGroup g in groups.ToList()) {
listView1.Items.Add(g.Name).SubItems.Add(g.Description);
}

来自 IDirectorySource<T>.ToList()方法,我使用反射来找出类型参数 T的适当构造函数.但是,由于 T给定一个接口(interface)类型,它根本找不到任何构造函数!

当然,我有一个 internal class Group : IGroup它实现了 IGroup界面。无论我多么努力,我都无法弄清楚如何通过我的实现类将构造函数从我的接口(interface)中取出。
[DirectorySchemaAttribute("group")]
public interface IGroup {
}

internal class Group : IGroup {
internal Group(DirectoryEntry entry) {
NativeEntry = entry;
Domain = NativeEntry.Path;
}
// Implementing IGroup interface...
}

ToList()我的方法 IDirectorySource<T>接口(interface)实现,找 T的构造函数如下:
internal class DirectorySource<T> : IDirectorySource<T> {
// Implementing properties...
// Methods implementations...
public IList<T> ToList() {
Type t = typeof(T)

// Let's assume we're always working with the IGroup interface as T here to keep it simple.
// So, my `DirectorySchema` property is already set to "group".
// My `DirectorySearcher` is already instantiated here, as I do it within the DirectorySource<T> constructor.
Searcher.Filter = string.Format("(&(objectClass={0}))", DirectorySchema)

ConstructorInfo ctor = null;
ParameterInfo[] params = null;

// This is where I get stuck for now... Please see the helper method.
GetConstructor(out ctor, out params, new Type() { DirectoryEntry });

SearchResultCollection results = null;

try {
results = Searcher.FindAll();
} catch (DirectoryServicesCOMException ex) {
// Handling exception here...
}

foreach (SearchResult entry in results)
entities.Add(ctor.Invoke(new object() { entry.GetDirectoryEntry() }));

return entities;
}
}

private void GetConstructor(out ConstructorInfo constructor, out ParameterInfo[] parameters, Type paramsTypes) {
Type t = typeof(T);

ConstructorInfo[] ctors = t.GetConstructors(BindingFlags.CreateInstance
| BindingFlags.NonPublic
| BindingFlags.Public
| BindingFlags.InvokeMethod);

bool found = true;

foreach (ContructorInfo c in ctors) {
parameters = c.GetParameters();

if (parameters.GetLength(0) == paramsTypes.GetLength(0)) {
for (int index = 0; index < parameters.GetLength(0); ++index) {
if (!(parameters[index].GetType() is paramsTypes[index].GetType()))
found = false;
}
if (found) {
constructor = c;
return;
}
}
}

// Processing constructor not found message here...
}

我的问题是 T将永远是 interface ,所以它永远找不到构造函数。

有没有比循环遍历我的所有程序集类型以实现我的接口(interface)更好的方法?

我不关心重写我的一段代码,我想一开始就做好,这样我就不需要一次又一次地回来。

编辑#1

按照 Sam 的建议,我现在将使用 INameName惯例。但是,是我还是有一些方法可以改进我的代码?

谢谢! =)

最佳答案

您在这里有几种可能性。

  • 山姆给了你一个答案。
  • 使用某种容器,见 Depencency injection .
  • 将类型 T 约束为具有默认构造函数 ( Constructor constraint ) 并将 SetEntry(DirectoryEntry) 添加到 IDirectoryEntry 接口(interface)。
  • 重构您的代码,以便您的目录源不会因创建新实例而负担。您可能有不同的搜索器,每个搜索器都返回正确的类型。

  • class DirectorySource<T>: IDirectorySource<T> {
    public DirectorySource(ISearcher<T> searcher) {
    Searcher = searcher;
    }
    public IList<T> ToList() {
    string filter = "...";
    return Searcher.FindAll(filter);
    }
    }
    class GroupSearcher: ISearcher<Group> {
    public IList<Group> FindAll(string filter) {
    entries = ...
    var entities = new List<Group>();
    foreach (var entry in entries)
    entities.Add(new Group(entry.GetDirectoryEntry());
    return entities;
    }
    }

    然后,您将像这样实例化您的 DirectorySource:
    IDirectorySource<Group> groups = new DirectorySource<Group>(new GroupSearcher());
  • ... :)

  • 编辑:
    您还可以使用 lambda 表达式。
    class DirectorySource<T>: IDirectorySource<T> {
    // Or you could put the parameter in constructor if this is not the only place
    // where you create new instances of T
    public IList<T> ToList(Func<DirectoryEntry, T> create) {
    ...
    foreach (var entry in entries)
    entities.Add(create(entry.GetDirectoryEntry()));
    return entities;
    }
    }

    IList<Group> groups = new DirectorySource<Group>().ToList(entry => new Group(entry));

    关于类(class)责任等,您是否对例如每种支持的类型进行了特殊处理。 Change(T)方法(或任何其他)?如果是这样,那么我仍然会重构并使用 IDirectoryEntryManager<T> (或其他名称)知道如何处理适当的类型。 DirectorySource然后可以使用该类来操作具体类型,而不会被不属于那里的细节所累。

    关于c# - 通过反射获取接口(interface)类型的构造函数,有没有比遍历类型更好的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3064238/

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