如何通过属性的值搜索命名空间中的类并返回一个对象?

时间:2016-03-31 00:46:38

标签: c# linq reflection system.reflection

我需要建造各种物品的工厂。要尽可能抽象。能够通过参数从过去的条件创建各种对象,但没有蹩脚的具体类。

我想通过将枚举值传递给工厂来实现这一点,并且它必须能够通过反射查找命名空间中的所有类,这些类使用的值与最后一个参数的值相同。

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

具体类的一个例子:

[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"

Obs。:图书馆应该是便携式的。 (.NET Framework 4.0.3,Silverlight 5,Windows 8,Windows Phone 8.1,Windows Phone Silverlight 8)

简而言之:鉴于枚举的值,如何使用反射检索将该参数用作属性的类的类型?

2 个答案:

答案 0 :(得分:1)

我想我明白你要做的事情。我编写了自己的类并对其进行了测试:

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

您还可以更进一步,并对其进行约束,以便您只返回从类型继承或实现接口的类型。否则你可以找回除属性之外没有任何共同点的类型。

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();

    }
}

答案 1 :(得分:0)

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