我已經瀏覽了StackOverflow以解決我的問題。雖然我不認爲這是一個獨特的問題,但我一直無法找到一個好的解決方案。如何有條件地實例化一個命名的Unity註冊類型
在我的WPF應用程序中,在我的viewmodels中,我需要調用一些服務來返回一些數據。這些服務被注入UnitOfWork,後者又被注入了DbContext。這個注入UnitOfWork的dbcontext應該根據一些標準而有所不同。
我在正確地做IoC容器註冊並在運行時注入正確的DbContext時遇到了問題。所以,如果有人可以填寫空白(在統一註冊以及它的用法)。我在下面的代碼中有一些內聯註釋,在這裏我遇到了麻煩並且需要幫助。謝謝。
如果有人能以正確的方式替換我的註冊碼,並教育我如何在我的WPF ViewModel類中使用它,那真是太棒了!謝謝。
最後一個注意事項:如果您在此代碼中發現編碼錯誤,請不要開始想知道如何編譯?這裏的代碼不是我真正的代碼。爲了簡化事情,我只是寫了起來。但它確實非常類似於我的真實應用程序代碼。
public interface IDBContext{}
public interface IUnitOfWork{}
public interface ISomeEntityService{}
public interface IRepository<T> where T : class
{ T GetSingle(Expression<Func<T, bool>> predicate); }
public class DBContext1 : IDBContext
{
public DBContext1(connString) : base(connString){}
}
public class DBContext2 : IDBContext
{
public DBContext2(connString) : base(connString){}
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly IDBContext context;
private readonly IDbSet<T> dbSet;
public Repository(IDBContext ctx)
{
context = ctx;
dbSet = ((DbContext)context).Set<T>();
}
public T GetSingle(Expression<Func<T, bool>> predicate)
{
return ((DbContext)context).Set<T>().SingleOrDefault(predicate);
}
}
public class UnitOfWork : IUnitOfWork
{
IDBContext ctx;
private Dictionary<string, dynamic> repositories;
public UnitOfWork(IDBContext context)
{
ctx = context;
}
public IRepository<T> Repository<T>() where T : class
{
if (repositories == null)
repositories = new Dictionary<string, dynamic>();
var type = nameof(T);
if (repositories.ContainsKey(type))
return (IRepository<T>)repositories[type];
var repositoryType = typeof(Repository<>);
repositories.Add(type, Activator.CreateInstance(repositoryType.MakeGenericType(typeof(T)), ctx));
return repositories[type];
}
public int SaveChanges()
{
return ctx.SaveChanges();
}
}
public class MyUnityBootstrapper : UnityBootstrapper
{
protected override void ConfigureContainer()
{
Container.RegisterType<IDBContext, DBContext1>("Context1");
Container.RegisterType<IDBContext, DBContext2>("Context2");
Container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
Container.RegisterType<IUnitOfWork, UnitOfWork>();
}
}
public class SomeEntityService : ISomeEntityService
{
private IUnitOfWork uow;
public ConsumerService(IUnitOfWork _uow)
{ uow = _uow; }
public SomeEntity GetSomeData(int id)
{
return uow.Repository<SomeEntity>().GetSingle(x => x.Id == id);
}
}
public class SomeViewModel : BindableBase
{
private readonly ISomeEntityService someService;
public SomeViewModel(ISomeEntityService _someService)
{
// when I call someService, I want to make sure it is using either
// DBContext1 or DBContext2 based on some condition I can set here.
// This is where I am totally stuck.
someService = _someService;
}
// get the repository instance with an id of 1000
someService.GetSomeData(1000);
}
/*
I could do something like this. But I am afraid, I am violating
two of the best practices recommendations.
1. I am creating a dependency to my IoC Container here.
2. I am using the container as a Service Locator
*/
public class SomeViewModel : BindableBase
{
private readonly ISomeEntityService someService;
public SomeViewModel()
{
var container = SomeHowGetTheContainer();
/*
1. Call Container.Resolve<IDBContext>(with the required context);
2. Use the retrieved context to inject into the UnitOfWork
3. Use the retrieved UnitOfWork to inject into the service
But that would be like throwing everything about best practices to the wind!
*/
someService = container.Resolve<ISomeEntityService>(/*do some magic here to get the right context*/)
}
// get the repository instance with an id of 1000
someService.GetSomeData(1000);
}
我會在抽象工廠實現中隱藏對容器的調用。工廠依賴容器是可以的。 – Haukinger
@Haukinger:在我的場景中,您可以請包括一些代碼來告訴我如何?這將有所幫助。謝謝。 –