Generics Unity和具有仿制药的汽车工厂
我们正在尝试使用Linq2SQl实现存储库模式,并且数据上下文是延迟初始化的 存储库类实现了IRepositoryGenerics Unity和具有仿制药的汽车工厂,generics,unity-container,Generics,Unity Container,我们正在尝试使用Linq2SQl实现存储库模式,并且数据上下文是延迟初始化的 存储库类实现了IRepository public class Repository<T> : IRepository<T> where T : class { private readonly Table<T> _table; public Repository(IDataContextAdapter dataContextAdapter)
public class Repository<T> : IRepository<T> where T : class
{
private readonly Table<T> _table;
public Repository(IDataContextAdapter dataContextAdapter)
{
_table = dataContextAdapter.Context.GetTable<T>();
}
...
}
public class UserDataAccess : IUserDataAccess
{
private readonly IRepository<User> _userRepository;
public UserDataAccess(IDataContextAdapter dataContextAdapter,
Func<IDataContextAdapter, IRepository<User>> userRepository)
{
_userRepository = userRepository(dataContextAdapter);
}
}
公共类存储库:IRepository,其中T:class
{
私有只读表_表;
公共存储库(IDataContextAdapter dataContextAdapter)
{
_table=dataContextAdapter.Context.GetTable();
}
...
}
数据访问使用对存储库的委托
public class Repository<T> : IRepository<T> where T : class
{
private readonly Table<T> _table;
public Repository(IDataContextAdapter dataContextAdapter)
{
_table = dataContextAdapter.Context.GetTable<T>();
}
...
}
public class UserDataAccess : IUserDataAccess
{
private readonly IRepository<User> _userRepository;
public UserDataAccess(IDataContextAdapter dataContextAdapter,
Func<IDataContextAdapter, IRepository<User>> userRepository)
{
_userRepository = userRepository(dataContextAdapter);
}
}
公共类UserDataAccess:IUserDataAccess
{
私有只读IRepository用户存储库;
公共用户数据访问(IDataContextAdapter dataContextAdapter,
Func用户存储库)
{
_userRepository=userRepository(dataContextAdapter);
}
}
我想知道如何在unity容器中通用地定义存储库
目前我有以下内容,但我不想对每个具体的存储库类(如User、Employer等)重复它
UnityContainer.RegisterType<Func<IDataContextAdapter, IRepository<User>>>(
new InjectionFactory(c =>
new Func<IDataContextAdapter, IRepository<User>>(
context => new Repository<User>(context))
)
);
UnityContainer.RegisterType(
新注射工厂(c=>
新职能(
上下文=>新存储库(上下文))
)
);
我正在寻找一种通用定义类型的方法,比如
UnityContainer.RegisterType<Func<IDataContextAdapter, IRepository<T>>>(
new InjectionFactory(c =>
new Func<IDataContextAdapter, IRepository<T>>(
context => new Repository<T>(context))
)
);
UnityContainer.RegisterType(
新注射工厂(c=>
新职能(
上下文=>新存储库(上下文))
)
);
我曾尝试在“”上应用typeof操作,但没有取得多大成功。我不明白您试图实现的目标,但我提出了一个建议,即我心目中的逻辑是什么 首先释放你的代表。(或解释它的用途)。通过以下方式定义您的UserDataAccess:
public class UserDataAccess : IUserDataAccess
{
private readonly IRepository<User> _userRepository;
public UserDataAccess(IRepository<User> userRepository)
{
_userRepository = userRepository;
}
}
公共类UserDataAccess:IUserDataAccess
{
私有只读IRepository用户存储库;
公共用户数据访问(IRepository userRepository)
{
_userRepository=userRepository;
}
}
现在,您的注册将如下所示:
DataContextAdapter context = new DataContextAdapter();
UnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType(typeof (IRepository<>), typeof (Repository<>));
unityContainer.RegisterType<IUserDataAccess, UserDataAccess>();
unityContainer.RegisterInstance<IDataContextAdapter>(context);
IUserDataAccess test = unityContainer.Resolve<IUserDataAccess>();
public class GenericDataServiceFactory<TResult, TModel>
{
private UnityContainer container;
private Func<IDataContextAdapter, IRepository<TModel>> _repositoryFactory;
public GenericDataServiceFactory(Func<IDataContextAdapter, IRepository<TModel>> repositoryFactory)
{
_repositoryFactory = repositoryFactory;
}
public TResult CreateUserDataAccess(IDataContextAdapter dataContextAdapter)
{
Type targerType = typeof (TResult);
// Via reflection find constructor like this
// TResult(IDataContextAdapter dataContextAdapter, Func<IDataContextAdapter,IRepository<Something>> repositoryFactory)
// Invoke it with dataContextAdapter and _repositoryFactory and return the result
return newObject;
}
}
DataContextAdapter context=newdatacontextadapter();
UnityContainer UnityContainer=新的UnityContainer();
RegisterType(typeof(IRepository),typeof(Repository));
unityContainer.RegisterType();
unityContainer.RegisterInstance(上下文);
然后你像这样解决:
DataContextAdapter context = new DataContextAdapter();
UnityContainer unityContainer = new UnityContainer();
unityContainer.RegisterType(typeof (IRepository<>), typeof (Repository<>));
unityContainer.RegisterType<IUserDataAccess, UserDataAccess>();
unityContainer.RegisterInstance<IDataContextAdapter>(context);
IUserDataAccess test = unityContainer.Resolve<IUserDataAccess>();
public class GenericDataServiceFactory<TResult, TModel>
{
private UnityContainer container;
private Func<IDataContextAdapter, IRepository<TModel>> _repositoryFactory;
public GenericDataServiceFactory(Func<IDataContextAdapter, IRepository<TModel>> repositoryFactory)
{
_repositoryFactory = repositoryFactory;
}
public TResult CreateUserDataAccess(IDataContextAdapter dataContextAdapter)
{
Type targerType = typeof (TResult);
// Via reflection find constructor like this
// TResult(IDataContextAdapter dataContextAdapter, Func<IDataContextAdapter,IRepository<Something>> repositoryFactory)
// Invoke it with dataContextAdapter and _repositoryFactory and return the result
return newObject;
}
}
IUserDataAccess test=unityContainer.Resolve();
将创建UserDataAccess,并将正确的封闭类型repostory注入构造函数。反过来,DataContextAdapter将被注入到repostory的构造函数中
更新1
根据原始问题中的信息,链接到您提供的上述内容,是否有以下内容不适用于您的原因
unityContainer.RegisterType(typeof (IRepository<>), typeof (Repository<>));
unityContainer.RegisterType<IUserDataAccess, UserDataAccess>();
DataContextAdapter context1 = new DataContextAdapter();
DataContextAdapter context2 = new DataContextAdapter();
IUnityContainer container1 = unityContainer.CreateChildContainer();
IUnityContainer container2 = unityContainer.CreateChildContainer();
container1.RegisterInstance<IDataContextAdapter>(context1);
container2.RegisterInstance<IDataContextAdapter>(context2);
IUserDataAccess test1 = container1.Resolve<IUserDataAccess>();
IUserDataAccess test2 = container2.Resolve<IUserDataAccess>();
unityContainer.RegisterType(typeof(IRepository)、typeof(Repository));
unityContainer.RegisterType();
DataContextAdapter context1=新DataContextAdapter();
DataContextAdapter context2=新DataContextAdapter();
IUnityContainer container1=unityContainer.CreateChildContainer();
IUnityContainer container2=unityContainer.CreateChildContainer();
容器1.注册状态(上下文1);
容器2.注册状态(上下文2);
IUserDataAccess test1=container1.Resolve();
IUserDataAccess test2=container2.Resolve();
我仍然认为没有理由对代表和注射工厂的复杂性。在不同的代码路径中需要不同的数据上下文,所以只需在容器中注入不同的实例,如下所示。当不再需要容器时,可以将其丢弃
您的需求中是否还有其他东西没有通过此解决方案得到满足
更新2
作为对您上述评论的回应,我想澄清一下,您不必使用上述方法预先注册或实例化上下文。您可以在使用它们的站点上进行操作:
// When you need context, obtain it
DataContextAdapter context1 = new DataContextAdapter();
//Register it for the local scope
IUnityContainer container1 = unityContainer.CreateChildContainer();
container1.RegisterInstance<IDataContextAdapter>(context1);
// Resolve the dependency
IUserDataAccess test1 = container1.Resolve<IUserDataAccess>();
// Use your interface
......
// Release and dispose your context
container1.Dispose
//需要上下文时,获取上下文
DataContextAdapter context1=新DataContextAdapter();
//为本地作用域注册它
IUnityContainer container1=unityContainer.CreateChildContainer();
容器1.注册状态(上下文1);
//解决依赖关系
IUserDataAccess test1=container1.Resolve();
//使用你的界面
......
//释放并处理您的上下文
容器1.处理
需要注意的主要一点是,您可以控制实例化它们的时间和地点。NET不允许使用部分闭合类型。这就是为什么你不能以一种通用的方式完成你想要实现的目标。在运行时,您可以使用像Func这样的打开类型,也可以使用像
Func这样的关闭类型
通过简化,Unity维护了一个类型映射字典,其中from类型是非泛型类型、泛型开放类型或泛型封闭类型。因此,不可能映射不属于这些类别的类型
如果我们能够找到一种在运行时与Func
匹配的好的、快速的方法,那么就有可能编写一个对Unity的扩展来实现解析。但是,似乎不可能在不使用反射的情况下进行这样的匹配,并且出于性能原因,您通常会在每次解析类型时尝试避免使用反射。在最坏的情况下,您在第一次分辨率期间仅使用反射来动态生成IL,该IL将在不进行反射的情况下创建对象。不幸的是,在我们的情况下,这是不可能的
在我看到的统一级别上解决此问题的唯一方法是每次请求Func
,检查是否已注册,如果未注册,则向动态生成的工厂注册
换句话说,没有简单的方法可以做到这一点
alt