c#Factory用于通用基类的具体实现

时间:2016-04-27 12:46:52

标签: c# generics factory

我有一个通用的Base类。 我有一个实现基类的具体类。

如何创建工厂类/方法来提供不同类型的具体类?

这是一个例子:

public class ReceiverBase<T>
    where T : IInterpreter
{ ... }

public class SpecialReceiver : ReceiverBase<OwnInterpreter> { ... }

public class ReceiverFactory<T>
    where T : ReceiverBase<IInterpreter>, new()

    public T Create(string type) {
        switch(type) {
            default:
                return new SpecialReceiver();
        }
    }
}

问题是ReceiverBase似乎不可能,因为编译器只希望类作为约束而不是接口。 第二个问题是我无法将SpecialReceiver转换为T.

有没有办法让这个工作?

===编辑:根据第一个答案添加了示例===

public interface IInterpreter
{
}

public class OwnInterpreter : IInterpreter
{
    public void Dispose()
    {
        throw new NotImplementedException();
    }

    public void DoSomething() { }
}



public abstract class ReceiverBase<T>
    where T : IInterpreter
{
    public T MyReceiver { get; set; }

    internal abstract void Start();
}

public class SpecialReceiver<T> : ReceiverBase<T>
    where T : IInterpreter, new()
{
    public void CheckSomething()
    {
        MyReceiver.DoSomething();
    }

    internal override void Start()
    {
        MyReceiver = new T();
    }
}

public class ReceiverFactory<T>
    where T : IInterpreter, new()
{
    public static ReceiverBase<T> Create(string type)
    {
        switch (type)
        {
            default:
                return new SpecialReceiver<T>();
        }
    }
}

问题是:MyReceiver.DoSomething();不管用。 另外,我必须像这样打电话给工厂:ReceiverFactory<OwnInterpreter>.Create("");我想这样做:ReceiverFactory.Create("SpecialReceiver");

3 个答案:

答案 0 :(得分:1)

您可以在工厂中使用通用方法:

class Program
{
    static void Main(string[] args)
    {
        var own = ReceiverFactory.Create<OwnInterpreter>();
        var other = ReceiverFactory.Create<OtherInterpreter>();
        own.Start();
        other.Start();
        Console.ReadLine();
    }
}
interface IInterpreter
{
    void DoSomething();
}

class OwnInterpreter : IInterpreter
{
    public void DoSomething() { Console.WriteLine("Own"); }
}

class OtherInterpreter : IInterpreter
{
    public void DoSomething() { Console.WriteLine("Other"); }
}

abstract class ReceiverBase<T> where T: IInterpreter, new()
{
    public T Interpreter { get; set; }
    public ReceiverBase()
    {
        Interpreter = new T();  
    }
    public void Start()
    {
        Interpreter.DoSomething();
    }
}

class SpecialReceiver : ReceiverBase<OwnInterpreter> { }
class OtherReceiver : ReceiverBase<OtherInterpreter> { }

static class ReceiverFactory
{
    private static Dictionary<string, object> factories = new Dictionary<string, object>();
    static ReceiverFactory()
    {
        RegisterFactory(() => new SpecialReceiver());
        RegisterFactory(() => new OtherReceiver());
    }
    public static void RegisterFactory<T>(Func<ReceiverBase<T>> factory) where T : IInterpreter, new()
    {
        factories.Add(typeof(T).FullName, factory);
    }
    public static ReceiverBase<T> Create<T>() where T : IInterpreter, new()
    {
        var type = typeof(T);
        return ((Func<ReceiverBase<T>>)factories[type.FullName]).Invoke();
    }
}

事实上,你不需要“new()”约束,因为你使用工厂。

答案 1 :(得分:0)

我建议您将代码更改为:

    public class ReceiverBase<T> where T : IInterpreter
    {
    }

    public interface IInterpreter
    {
    }

    public class SpecialReceiver<T> : ReceiverBase<T>
        where T : IInterpreter
    {
    }

    public class OwnInterpreter : IInterpreter
    {
    }

    public class ReceiverFactory<T> where T : IInterpreter, new()
    {
        public ReceiverBase<T> Create(string type)
        {
            switch (type)
            {
                default:
                    return new SpecialReceiver<T>();
            }
        }
    }

您无法在案例中返回T的原因是SpecialReceiverReceiverBase<IInterpreter>之间没有隐式转换。

答案 2 :(得分:0)

我能够找到适合我需求的解决方案。 我添加了另一个接口IReciver,它定义了我真正需要的属性和成员。工厂方法返回IReceiver,因此我可以省略所有与泛型有关的绑定问题。有时这很容易。 :)

public interface IInterpreter { }

public interface IReceiver
{
    bool Enabled { get; set; }
}

public class OwnInterpreter : IInterpreter
{
    public void DoSomething() { }
}

public abstract class ReceiverBase<T> : IReceiver
    where T : IInterpreter, new()
{
    public T MyReceiver { get; set; }

    internal abstract void Start();

    private bool _isEnabled;
    public bool Enabled { get { return _isEnabled; } set { _isEnabled = value; OnEnable(value); } }

    internal abstract void OnEnable(bool isEnabled);

    protected ReceiverBase()
    {
        MyReceiver = new T();
    }
}

public class SpecialReceiver : ReceiverBase<OwnInterpreter>
{
    public void CheckSomething()
    {
        MyReceiver.DoSomething();
    }

    internal override void Start()
    {
        // just for testing puropses
        MyReceiver = new OwnInterpreter();
    }

    internal override void OnEnable(bool isEnabled)
    {
        MyReceiver = isEnabled ? new OwnInterpreter() : null;
    }
}

public class ReceiverFactory
{
    public static IReceiver Create(string type)
    {
        switch (type)
        {
            default:
                return new SpecialReceiver();
        }
    }
}

public class Program
{
    [STAThread]
    public static void Main()
    {
        ReceiverFactory.Create("");
    }
}