我正在尝试模拟我可以在 Ninject 中配置的行为,但只使用 Unity。
我正在尝试使用缓存存储库模式,给定以下类和接口(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<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>())});
您可以改用自定义注入(inject)工厂,这只是“编写您自己的工厂函数”的一种奇特说法。
// 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'!"
}
}
关于c# - 基于具体类型在 Unity 中注册泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24369425/