Generics Unity和具有仿制药的汽车工厂

Generics 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)

我们正在尝试使用Linq2SQl实现存储库模式,并且数据上下文是延迟初始化的

存储库类实现了IRepository

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