创建具有动态注入类的委托

时间:2018-07-12 12:16:35

标签: c# reflection dependency-injection delegates ioc-container

由于我处理反射的数据量很大并且存在性能问题(如我所了解的here),因此我正在将自己从反射到委托的处理算法进行更改。所以我的旧代码是一个简单的反映,如下所示:

var result = method.Invoke(service, new object[] { viewModel });

方法是MethodInfo的地方,service是具有称为Add()的通用方法的服务类。所有服务都具有该方法(不是通用方法),并且该处理算法可以在任何服务上运行,因此,服务(实例)是动态的。通过Unity可以解决。

这是一个working demo,具有我想要实现的类似代码:

using System;
using System.Reflection;

// This is the delegate declaration
public delegate string ServiceDelegate(ViewModel vm);

public class Program
{
    public static void Main()
    {
        // Here the 'Service' class is created by a IoC container
        object service = DependencyInjectionSimulator.Resolve();
        Type type = service.GetType();
        MethodInfo method = type.GetMethod("Add");

        ServiceDelegate serviceDelegate = (ServiceDelegate)Delegate.CreateDelegate(typeof(ServiceDelegate), service, method);

        var car = new CarViewModel();

        Console.WriteLine(serviceDelegate(car));
    }
}

// This is the 'Service' base class. It will be created dynamically and all services has the Add() method with a 'ViewModel' inherited class
public class Service
{
    public string Add(CarViewModel input)
    {
        return input.Name;
    }
}

// All 'Add()' method of services will work with a parameter that inherits 'ViewModel'
public class ViewModel
{
    public string Name { get; set; }
}

public class CarViewModel : ViewModel
{
}

// Let's pretend this is a Unity Resolver
public static class DependencyInjectionSimulator
{
    public static object Resolve()
    {
        return new Service();
    }
}

尽管我不确定是否有可能,但我希望通过尝试达到的目的可以澄清这一点。

1 个答案:

答案 0 :(得分:1)

您的DI框架将永远只为您提供一个代表您所要类型的对象,因此您永远不必担心委托或反射。例如,让我们将您的DI模拟器更新为:

public static class DependencyInjectionSimulator
{
    public static TService Resolve<TService>() 
        where TService : class
    {
        //So this only works for the one type right now, but hey, it's only a simulator!
        return new Service() as TService;
    }
}

我还建议您为服务使用接口,这是一种良好的习惯,并且将来会在单元测试之类的方面有所帮助:

public interface IService
{
    void Add(CarViewModel input);
}

public class Service : IService
{
    public void Add(CarViewModel input)
    {

    }
}

现在您的代码简化为:

var service = DependencyInjectionSimulator.Resolve<IService>();
var car = new CarViewModel();
service.Add(car);