Unity - 基于模型类型解决通用接口的实现

时间:2018-02-27 19:17:25

标签: c# generics dependency-injection unity-container

我是Unity的新手,在涉及实现通用接口的类时遇到了问题。

假设我有一个控制器和一个服务类,他们打算根据传入控制器的类型标识符调用业务层。这是我的布局:

型号:

public interface IModel
{
    string Name { get; }
}
public class MyOrder : IModel
{
    public string Name { get { return "Order"; } }
}
public class MyInvoice : IModel
{
    public string Name { get { return "Invoice"; } }
}

业务逻辑:

public interface ILogic
{
    string GetModelName(IModel myModel);
}
public class MyOrderLogic : ILogic
{
    public string GetModelName(IModel myModel)
    {
        return "MyOrderLogic : " + myModel.Name;
    }
}
public class MyInvoiceLogic : ILogic
{
    public string GetModelName(IModel myModel)
    {
        return "MyInvoiceLogic : " + myModel.Name;
    }
}

public class LogicFactory
{
    Func<IModel, ILogic> logicResolver;

    public LogicFactory(Func<IModel, ILogic> resolver)
    {
        logicResolver = resolver;
    }

    public ILogic GetLogicForModel(IModel model)
    {
        return logicResolver(model);
    }
}

服务:

public class MySingleService
{

    private LogicFactory factory;

    public MySingleService(LogicFactory f)
    {
        this.factory = f;
    }

    public IModel GetModel(int typeId, int objectId)
    {
        IModel model;
        // This would really call Entity Framework context
        switch (typeId)
        {
            case 1:
                model = new MyOrder();
                break;
            default:
                model = new MyInvoice();
                break;
        }
        return model;
    }

    public void DoSomething(IModel model)
    {
        var logic = factory.GetLogicForModel(model);
        var name = logic.GetModelName(model);
        Console.WriteLine(name);
    }
}

控制器:

public class MyController
{
    MySingleService service;

    public MyController(MySingleService s)
    {
        this.service = s;
    }

    public void DoAnAction(int typeId, int objectId)
    {
        var model = service.GetModel(typeId, objectId);
        service.DoSomething(model);
    }
}

当我像这样配置我的Unity容器时,这一切都很好用

var container = new UnityContainer();            
container.RegisterType<ILogic, MyOrderLogic>("MyOrder");
container.RegisterType<ILogic, MyInvoiceLogic>("MyInvoice");

Func<IModel, ILogic> resolver = (myModel) => container.Resolve<ILogic>(myModel.GetType().Name);
var logicFactory = new LogicFactory(resolver);
container.RegisterInstance<LogicFactory>(logicFactory);

var controller = container.Resolve<MyController>();

我的问题是我想限制业务逻辑类,以便它们只能在正确的模型上工作(即我希望MyOrderLogic只接受MyOrder)

我想让业务层使用泛型,如下所示:

 // Business Logic
public interface ILogic<T> where T : IModel
{
    string GetModelName(T myModel);
}
public class MyOrderLogic : ILogic<MyOrder>
{
    public string GetModelName(MyOrder myModel)
    {
        return "MyOrderLogic : " + myModel.Name;
    }
}
public class MyInvoiceLogic : ILogic<MyInvoice>
{
    public string GetModelName(MyInvoice myModel)
    {
        return "MyInvoiceLogic : " + myModel.Name;
    }
}

这导致了服务和控制器之间的各种问题。我不确定如何根据类型标识符正确解析* Logic类。我尝试做类似于ILogic<IModel> logic = new MyOrderLogic()的事情,但这显然没有用。

我正在寻找什么?有什么我可以添加到LogicFactory或其他东西吗?

我想避免使用单独的控制器和服务对象,因为它们只有重复的代码。

0 个答案:

没有答案