基于具体类型注册泛型类型在Unity [英] Register Generic Type in Unity Based On Concrete Type

查看:728
本文介绍了基于具体类型注册泛型类型在Unity的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图模仿我可以在Ninject,仅配置使用Unity,而不是行为。

I'm trying to emulate a behavior that I can configure in Ninject, only using Unity instead.

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

I am attempting to use the Cached Repository Pattern, given the following classes and interface:

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<的实际SQL资料库; T> 。在Ninject,我用下面的做到了这一点:(;>的typeof(IRepository<))

Basically, any time my application uses IRepository<T>, it should get an instance of CachedRepository<T>. But inside of CachedRepository<T> it should fetch the actual SQL repository of SqlRepository<T>. In Ninject, I have accomplished this using the following:

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

在团结,我将如何完成同样的事情?我对非通用库版本的作品:

In Unity, how would I accomplish the same thing? I have a version for non-generic repositories that works:

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



不过,这个语法不会与通用存储库在所有的工作,因为你不能说新SqlRepository<> 无需语法错误。 ?任何想法

But this syntax won't work at all with the generic repository, since you can't say new SqlRepository<> without having a syntax error. Any ideas?

推荐答案

假设你不想注册每一个人可以通用的,像这样的:

Assuming you don't want to register every individual possible generic, like this:

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



你也可以使用一个定制注塑厂,这是他说的只是一种奇特的方式写你自己。工厂函数

you could instead use a custom injection factory, which is just a fancy way of saying "write your own factory function."

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

这篇关于基于具体类型注册泛型类型在Unity的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆