Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 静态注册的工厂模式_C#_Factory_Static Constructor - Fatal编程技术网

C# 静态注册的工厂模式

C# 静态注册的工厂模式,c#,factory,static-constructor,C#,Factory,Static Constructor,我在尝试使用静态构造函数向以下工厂注册类型时遇到问题: public class Factory<T> { public static Factory<T> Instance { get { return _instance; } } private static Factory<T> _instance = new Factory<T>(); private Factory() { } static Facto

我在尝试使用静态构造函数向以下工厂注册类型时遇到问题:

 public class Factory<T>
{
    public static Factory<T> Instance { get { return _instance; } }

    private static Factory<T> _instance = new Factory<T>();
    private Factory() { }
    static Factory() { }

    static Dictionary<string, Type> _registeredType = new Dictionary<string, Type>();

    public void Register(string id, T obj)
    {
        if (obj.GetType().IsAbstract || obj.GetType().IsInterface)
            throw new ArgumentException("Cannot create instance of interface or abstract class");

        _registeredType.Add(id, obj.GetType());
    }

    public T Create(string id, params object[] parameters)
    {
        Type type;

        if(!_registeredType.TryGetValue(id, out type))
            throw new UnsupportedShapeException(id);

        return (T)Activator.CreateInstance(type, parameters);
    }
} 
公共类工厂
{
公共静态工厂实例{get{return\u Instance;}}
私有静态工厂_实例=新工厂();
私有工厂(){}
静态工厂(){}
静态字典_registeredType=新字典();
公共无效寄存器(字符串id,T obj)
{
if(obj.GetType().IsAbstract | | obj.GetType().IsInterface)
抛出新ArgumentException(“无法创建接口或抽象类的实例”);
_Add(id,obj.GetType());
}
公共T创建(字符串id,参数对象[]参数)
{
类型;
if(!\u registeredType.TryGetValue(id,输出类型))
抛出新的不受支持的ShapeException(id);
return(T)Activator.CreateInstance(类型、参数);
}
} 
那么,如果我使用静态构造函数进行注册,它将不起作用:

    public interface IShape
{
    string print { get; }
}

public class Circle : IShape
{
    static Circle()
    {
        Factory<IShape>.Instance.Register("Circle", new Circle());
    }

    public string print
    {
        get
        {
            return "Circle";
        }
    }
}
公共接口IShape
{
字符串打印{get;}
}
公共阶级圈子:IShape
{
静态圆()
{
Register(“Circle”,new Circle());
}
公共字符串打印
{
得到
{
返回“圈”;
}
}
}

我哪里做错了?这家工厂似乎建得很好,但我就是不能让它运转。干杯。

我不是100%确定我知道您在追求什么,但是,最好让controller的esqe类包含工厂实例化。但是,构造函数注入在静态类或子类上不起作用

public static class StaticFactoryClassController
{
    private static readonly IStaticFactoryService service=AppServiceFactory.Instance.Create<IStaticFactoryService>();

    public static void DoSomething() 
    {
        Service srv = new StaticFactoryClassService(service);
        srv.DoSomething(); 
    }
}
最后是绑定接口--


这不是答案,而是建议。首先,当您使用泛型类时,CLR实际上为每个实现创建类。此类将具有不同的静态变量,并且不能对所有类使用一个工厂。好消息是您可以使用泛型方法而不是泛型类。您甚至不需要创建
T
对象的实例:

public class Factory
{
    public static Factory Instance { get { return _instance; } }

    private static Factory _instance = new Factory();
    private Factory() { }

    static Dictionary<string, Type> _registeredType = new Dictionary<string, Type>();

    public void Register<T>(string id)
    {
        var type = typeof(T);
        if (type.IsAbstract || type.IsInterface)
            throw new ArgumentException("Cannot create instance of interface or abstract class");

        _registeredType.Add(id, type);
    }

    public T Create<T>(string id, params object[] parameters)
    {
        Type type;

        if(!_registeredType.TryGetValue(id, out type))
            throw new UnsupportedShapeException(id);

        return (T) Activator.CreateInstance(type, parameters);
    }
} 

静态协构造函数在某些代码首次访问某个类时执行,您是否在某处访问该类?请更具体地说明它是如何工作的。对不起,我应该更清楚一些,我正在尝试实现这一点:我应该更具体一些。如果我把这段代码编译出来(还有几个编译器错误需要修复),它什么也做不了。因此,您必须有1)一些未显示的附加代码,2)对该代码的输出应该是什么的一些期望,以及3)实际输出(这是不同的)。请添加这些信息。我实际上没有在任何地方引用具体的类。。哇,真糟糕!干杯。这很好,但是考虑到OP的模式,我认为
Create
应该返回
object
,而不是
T
,并且不是泛型的,因此字符串
id
是唯一确定输出类型的方法。当类型不兼容并且抛出异常时(泛型只是一个转换提示),它还避免了工厂成为任何不正确转换的位置。这导致代码(对我来说)对正在发生的事情更加清楚:
var firstCircle=(Circle)Factory.Instance.Create(“Circle”);var secondCircle=(IShape)Factory.Instance.Create(“Circle”)
@ErikE实际上,我们可以比较Create方法中dictionary和generic参数中的类型,如果type不是implements/inherits,则抛出一个自定义异常,该异常将显示真正的问题。但在工厂内使用泛型参数和强制转换结果是相同的,但有点“强类型”。依我拙见字符串就是一个字符串。在作者的场景中,是否有理由通过字符串标识符注册类型,或者他可以只使用Activator.CreateInstance的通用包装器?@Vadim我喜欢这样!对于我正在使用的场景,我确实需要使用一个ID,但我认为如果没有它,您的实现可能会非常有效,就像您所说的,泛型类型将是它所需要的唯一ID。所以Create();在使用
Factory.Instance.Create()的最简单场景中对于具体的类,它可以只是一个包装器:
public T Create(params object[]parameters){return(T)Activator.CreateInstance(typeof(T),parameters);}
如果他是通过字符串创建类型,那么字符串本身就可以工作。还必须指定一个类型,这将破坏整个场景。
public interface IStaticFactoryService
{
    DoSomething();
}  
public class Factory
{
    public static Factory Instance { get { return _instance; } }

    private static Factory _instance = new Factory();
    private Factory() { }

    static Dictionary<string, Type> _registeredType = new Dictionary<string, Type>();

    public void Register<T>(string id)
    {
        var type = typeof(T);
        if (type.IsAbstract || type.IsInterface)
            throw new ArgumentException("Cannot create instance of interface or abstract class");

        _registeredType.Add(id, type);
    }

    public T Create<T>(string id, params object[] parameters)
    {
        Type type;

        if(!_registeredType.TryGetValue(id, out type))
            throw new UnsupportedShapeException(id);

        return (T) Activator.CreateInstance(type, parameters);
    }
} 
Factory.Instance.Register<Circle>("Circle");
var firstCircle = Factory.Instance.Create<Circle>("Circle");
var secondCircle = Factory.Instance.Create<IShape>("Circle");