繁体   English   中英

基于混凝土类型在Unity中注册通用类型

[英]Register Generic Type in Unity Based On Concrete Type

我正在尝试模拟我可以在Ninject中配置的行为,而只使用Unity。

我正在尝试使用Cached Repository Pattern,给定以下类和接口:

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> ,它应该得到一个CachedRepository<T>的实例。 但是在CachedRepository<T>它应该获取SqlRepository<T>的实际SQL存储库。 在Ninject中,我使用以下方法完成了此操作:

ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(SqlRepository<>)).WhenInjectedExactlyInto(tyepof(CachedRepository<>));
ninjectModule.Bind(typeof(IRepository<>)).To(tyepof(CachedRepository<>));

在Unity中,我将如何完成同样的事情? 我有一个适用于非通用存储库的版本:

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

但是这种语法根本不适用于通用存储库,因为你不能说没有语法错误的new SqlRepository<> 有任何想法吗?

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

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>())});

你可以使用自定义注塑工厂,这只是说“编写自己的工厂功能”的一种奇特方式。

// 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'!"
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM