加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 22:18:20 所属栏目:百科 来源:网络整理
导读:我想对以下工厂的实施提出一些反馈意见: public enum DietType {Carnivore,Herbivore,Omnivore};[AttributeUsage(System.AttributeTargets.Class)]public class DietTypeAttribute : Attribute{ public DietType dietType { get; private set; } public Die
我想对以下工厂的实施提出一些反馈意见:

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,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,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'
}

编辑:
您实际上并不需要此模板类型

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

    protected AbstractFactory()
    {
        types = (from assembly in AppDomain.CurrentDomain.GetAssemblies()
                 from type in assembly.GetTypes()
                 let attributes = type.GetCustomAttributes(typeof(FactoryAttribute),true)
                 where (attributes.Any()) && (typeof(T).IsAssignableFrom(type)) && (type.IsClass)
                 select
                 new
                 {
                     dietEnum = (Enum)((FactoryAttribute)attributes.First()).Something,param);
    }
}

你的工厂很简单:

class DietFactory : AbstractFactory<Diet>
{
    public DietFactory()
    {
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读