C# 在c中使用反射的自注册工厂

C# 在c中使用反射的自注册工厂,c#,linq,reflection,enums,factory,C#,Linq,Reflection,Enums,Factory,我想了解有关以下工厂实施的一些反馈: public enum DietType {Carnivore, Herbivore, Omnivore}; [AttributeUsage(System.AttributeTargets.Class)] public class DietTypeAttribute : Attribute { public DietType dietType { get; private set; } public DietTypeAttribute(D

我想了解有关以下工厂实施的一些反馈:

public enum DietType {Carnivore, Herbivore, Omnivore};

[AttributeUsage(System.AttributeTargets.Class)]
public class DietTypeAttribute : Attribute
{
    public DietType dietType { get; private set; }

    public DietTypeAttribute(DietType dietType)
    {
        this.dietType = dietType;
    }
}

public abstract class Diet { }

[DietTypeAttribute(DietType.Carnivore)]
public class Carnivore : Diet
{
}

[DietTypeAttribute(DietType.Herbivore)]
public class Herbivore : Diet
{
}

abstract class AbstractFactory<T> where T : class
{
    protected Dictionary<Enum, Type> types;

    protected AbstractFactory()
    {
    }

    public T CreateInstance(Enum id, params object[] param)
    {
        return (T)Activator.CreateInstance(types[id], param);
    }
}

class DietFactory : AbstractFactory<Diet>
{
    public DietFactory()
    {
        types = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                 from type in assembly.GetTypes()
                 let attributes = type.GetCustomAttributes(typeof(DietTypeAttribute), true)
                 where (attributes.Any()) && (typeof(Diet).IsAssignableFrom(type)) && (type.IsClass)
                 select
                 new
                 {
                     dietEnum = (Enum)((DietTypeAttribute)attributes.First()).dietType,
                     dietType = type
                 }).ToDictionary(x => x.dietEnum, x => x.dietType);
    }
}
用法:

static void Main(string[] args)
    {
        AbstractFactory<Diet> factory = new DietFactory();
        Diet diet = factory.CreateInstance(DietType.Carnivore);
    }
其主要思想是使用枚举而不是字符串来自注册类。我正在努力找到一种使注册通用的方法,这样就可以避免在LINQ查询中指定属性类


欢迎任何帮助

试试这样的

public enum DietType {Carnivore, Herbivore, Omnivore};

public class FactoryAttribute : Attribute
{
    public Object Something { get; protected set; }
}

[AttributeUsage(System.AttributeTargets.Class)]
public class DietTypeAttribute : FactoryAttribute
{
    public DietTypeAttribute(DietType dietType)
    {
        this.Something = dietType;
    }
}

public abstract class Diet { }

[DietTypeAttribute(DietType.Carnivore)]
public class Carnivore : Diet
{
}

[DietTypeAttribute(DietType.Herbivore)]
public class Herbivore : Diet
{
}

abstract class AbstractFactory<T> where T : class
{
    protected Dictionary<Enum, Type> types;

    protected AbstractFactory()
    {
    }

    protected void Register<TEnumType, TSubType>()
        where TEnumType: FactoryAttribute
    {

        types = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                 from type in assembly.GetTypes()
                 let attributes = type.GetCustomAttributes(typeof(TEnumType), true)
                 where (attributes.Any()) && (typeof(TSubType).IsAssignableFrom(type)) && (type.IsClass)
                 select
                 new
                 {
                     dietEnum = (Enum)((TEnumType)attributes.First()).Something,
                     dietType = type
                 }).ToDictionary(x => x.dietEnum, x => x.dietType);
    }

    public T CreateInstance(Enum id, params object[] param)
    {   
        return (T)Activator.CreateInstance(types[id], param);
    }
}

class DietFactory : AbstractFactory<Diet>
{
    public DietFactory()
    {
        Register<DietTypeAttribute, Diet>(); 
    }
}
和测试

void Main()
{
    AbstractFactory<Diet> factory = new DietFactory();
    Diet diet = factory.CreateInstance(DietType.Carnivore);
    //diet is a 'Carnivore'
    diet = factory.CreateInstance(DietType.Herbivore);
    //diet is a 'Herbivore'
}
编辑: 实际上,您不需要为此使用模板类型

你们的工厂就是:

class DietFactory : AbstractFactory<Diet>
{
    public DietFactory()
    {
    }
}
为什么要使用枚举?仅拥有具有CreateInstance的工厂是不够的?
class DietFactory : AbstractFactory<Diet>
{
    public DietFactory()
    {
    }
}