如何通过属性值和 return 对象在命名空间中搜索 class?

How to search a class within a namespace by the value of an attribute and return an object?

我需要制作各种对象的工厂。尽可能抽象。能够通过参数从过去的条件创建各种对象,但不知道具体的 classes.

我想通过将枚举的值传递给工厂来完成此操作,并且它必须能够通过反射查找名称空间中所有使用值为的属性的 classes与最后一个参数相同。

我将留下以下代码片段作为参考。

具体例子class:

[Batatinha(SaborCode.Churrasco)]
internal class BatatinhaChurrasco : AbstractBatatinha
{
    public override string Sabor
    {
        get { return "Churrasco"; }
    }
}

这个工厂的例子:

internal class BatatinhaFactory
{
    internal AbstractBatatinha GetBatatinha(SaborCode sabor)
    {
        // Some logic ... possibly using reflection.
    }
}

所需调用示例:

AbstractBatatinha batatinha = new BatatinhaFactory().GetBatatinha(SaborCode.Churrasco);
Console.WriteLine(batatinha.Sabor);
// ==> "Churrasco"

观察:库应该是可移植的。 (.NET Framework 4.0.3, Silverlight 5, Windows 8, Windows Phone 8.1, Windows Phone Silverlight 8)

简而言之:给定枚举值,如何使用反射检索使用参数作为属性的 class 类型?

我想我明白你想做什么。我自己写了 类 并测试了这个:

public enum AttributeTypes
{
    TypeA, TypeB
}

public class ReferencesEnumAttribute : Attribute
{
    public AttributeTypes AttributeType { get; set; }

    public ReferencesEnumAttribute(AttributeTypes attributeType)
    {
        AttributeType = attributeType;
    }
}

public class FindsClassesByAttributeAndEnumValue
{
    public Type[] FindClassesInAssemblyContaining<T>(AttributeTypes attributeType)
    {
        return typeof (T).Assembly.GetTypes()
            .Where(type => type.GetCustomAttributes(false)
                .Any(attribute => attribute is ReferencesEnumAttribute
                  && ((ReferencesEnumAttribute) attribute).AttributeType == attributeType))
            .ToArray();

    }
}

然后是几个类属性:

[ReferencesEnum(AttributeTypes.TypeA)]
public class HasAttribute {}

[ReferencesEnum(AttributeTypes.TypeA)]
public class AlsoHasAttribute{}

[ReferencesEnum(AttributeTypes.TypeB)]
public class DoesntHaveAttribute {}

最后是单元测试:

[TestMethod]
public void GetClassesWithAttribute()
{
    var finder = new FindsClassesByAttributeAndEnumValue();
    var types = finder.FindClassesInAssemblyContaining<ReferencesEnumAttribute>(AttributeTypes.TypeA);
    Assert.AreEqual(2, types.Length);
}

您还可以更进一步,对其施加约束,这样您就只能 return 从类型继承或实现接口的类型。否则你可能会得到除了属性之外没有任何共同点的类型。

public class FindsClassesByAttributeAndEnumValue
{
    public Type[] FindClassesInAssemblyContaining<TContains,TInheritsFrom>(AttributeTypes attributeType)
        where TInheritsFrom : class
    {
        return typeof (TContains).Assembly.GetTypes()
            .Where(type => 
                type.IsAssignableFrom(typeof(TInheritsFrom))
                && type.GetCustomAttributes(false)
                .Any(attribute => attribute is ReferencesEnumAttribute
                                  && ((ReferencesEnumAttribute) attribute).AttributeType == attributeType))
            .ToArray();

    }
}

不建议在工厂中使用反射 类 因为它可能会导致您的代码出现性能问题。在代码中的某处使用反射,您将不得不使用 Activator.CreateInstance() 方法,这会导致您的应用程序出现性能问题,请查看此 post:Does System.Activator.CreateInstance(T) have performance issues big enough to discourage us from using it casually?