C# 基于具体类型在Unity中注册泛型类型

C# 基于具体类型在Unity中注册泛型类型,c#,generics,inversion-of-control,ninject,unity-container,C#,Generics,Inversion Of Control,Ninject,Unity Container,我试图模拟一种可以在Ninject中配置的行为,只使用Unity 考虑到以下类和接口,我正在尝试使用缓存存储库模式: public interface IRepository<T> { T Get(); } public class SqlRepository<T> : IRepository<T> where T : new() { public T Get() { Console.WriteLine("Ge

我试图模拟一种可以在Ninject中配置的行为,只使用Unity

考虑到以下类和接口,我正在尝试使用缓存存储库模式:

public interface IRepository<T>
{
    T Get();
}

public class SqlRepository<T> : IRepository<T>
    where T : new()
{
    public T Get()
    {
        Console.WriteLine("Getting object of type '{0}'!", typeof(T).Name);
        return new T();
    }
}

public class CachedRepository<T> : IRepository<T>
    where T : class
{
    private readonly IRepository<T> repository;

    public CachedRepository(IRepository<T> repository)
    {
        this.repository = repository;
    }

    private T cachedObject;
    public T Get()
    {
        if (cachedObject == null)
        {
            cachedObject = repository.Get();
        }
        else
        {
            Console.WriteLine("Using cached repository to fetch '{0}'!", typeof(T).Name);
        }
        return cachedObject;
    }
}
公共接口IRepository
{
T Get();
}
公共类SqlRepository:IRepository
其中T:new()
{
公共部门得不到
{
WriteLine(“获取类型为“{0}”!”的对象,类型为(T).Name);
返回新的T();
}
}
公共类缓存存储:IRepository
T:在哪里上课
{
私有只读存储库;
公共缓存存储库(IRepository存储库)
{
this.repository=存储库;
}
私人纪念印;
公共部门得不到
{
if(cachedObject==null)
{
cachedObject=repository.Get();
}
其他的
{
WriteLine(“使用缓存的存储库获取“{0}”!”,typeof(T.Name);
}
返回cachedObject;
}
}
基本上,每当我的应用程序使用
IRepository
,它都应该获得
CachedRespository
的实例。但是在
CachedRepository
内部,它应该获取
SqlRepository
的实际SQL存储库。在Ninject中,我使用以下方法实现了这一点:

ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(SqlRepository<>)).WhenInjectedExactlyInto(tyepof(CachedRepository<>));
ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(CachedRepository<>));
ninjectModule.Bind(typeof(IRepository)).To(tyepof(SqlRepository)).WhenInjectedExactlyInto(tyepof(CachedRepository));
Bind(typeof(IRepository)).To(tyepof(CachedRepository));
在团结中,我将如何完成同样的事情?我有一个适用于非通用存储库的版本:

UnityContainer container = new UnityContainer();
container.RegisterType<IWidgetRepository, CachedWidgetRepository>(new InjectionMember[] { new InjectionConstructor(new SqlWidgetRepository()) });
UnityContainer container=newunitycontainer();
RegisterType(new InjectionMember[]{new InjectionConstructor(new SqlWidgetRepository())});

但是这种语法在通用存储库中根本不起作用,因为如果没有语法错误,就不能说
newsqlrepository
。有什么想法吗?

假设您不想注册每个可能的泛型,如下所示:

container.RegisterType<IRepository<Things>, CachedRepository<Things>>(new InjectionMember[] {new InjectionConstructor(new SqlRepository<Things>())});

container.RegisterType<IRepository<OtherThings>, CachedRepository<OtherThings>>(new InjectionMember[] {new InjectionConstructor(new SqlRepository<OtherThings>())});
container.RegisterType(new InjectionMember[]{new InjectionConstructor(new SqlRepository())});
RegisterType(new InjectionMember[]{new InjectionConstructor(new SqlRepository())});
您可以使用定制的注入工厂,这只是一种说“编写您自己的工厂函数”的奇特方式

//我们将要求Unity制作其中一个,因此它必须解决IRepository问题
公共类使用的东西
{
公开的只读信息;
公共用途物品(IRepository Things Repo)
{
this.ThingsRepo=ThingsRepo;
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var container=new UnityContainer();
//定义自定义注射工厂。
//它使用反射根据请求的泛型类型创建对象。
var cachedRepositoryFactory=新注入工厂((ctr,type,str)=>
{
var genericType=type.GenericTypeArguments[0];
var sqlRepoType=typeof(SqlRepository);
var sqlRepoInstance=Activator.CreateInstance(sqlRepoType);
var cachedRepoType=Activator.CreateInstance(类型,sqlRepoInstance);
返回cachedRepoType;
});
//为IRepository注册我们奇特的爱思考功能
RegisterType(typeof(IRepository)、typeof(CachedRepository)、新注入成员[]{cachedRepositoryFactory});
//现在用团结来解决一些问题
var usesThings=container.Resolve();
使用Things.ThingsRepo.Get();/“获取'Things'类型的对象!”
使用Things.ThingsRepo.Get();/“使用缓存存储库获取‘东西’!”
}
}
相关:
// We will ask Unity to make one of these, so it has to resolve IRepository<Things>
public class UsesThings
{
    public readonly IRepository<Things> ThingsRepo;

    public UsesThings(IRepository<Things> thingsRepo)
    {
        this.ThingsRepo = thingsRepo;
    }
}


class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();

        // Define a custom injection factory.
        // It uses reflection to create an object based on the requested generic type.
        var cachedRepositoryFactory = new InjectionFactory((ctr, type, str) =>
            {
                var genericType = type.GenericTypeArguments[0];
                var sqlRepoType = typeof (SqlRepository<>).MakeGenericType(genericType);
                var sqlRepoInstance = Activator.CreateInstance(sqlRepoType);
                var cachedRepoType = Activator.CreateInstance(type, sqlRepoInstance);
                return cachedRepoType;
            });

        // Register our fancy reflection-loving function for IRepository<>
        container.RegisterType(typeof(IRepository<>), typeof(CachedRepository<>), new InjectionMember[] { cachedRepositoryFactory });

        // Now use Unity to resolve something
        var usesThings = container.Resolve<UsesThings>();
        usesThings.ThingsRepo.Get(); // "Getting object of type 'Things'!"
        usesThings.ThingsRepo.Get(); // "Using cached repository to fetch 'Things'!"
    }
}