Ich habe mich in StackOverflow nach einer Lösung für mein Problem umgesehen. Obwohl ich nicht denke, dass dies ein einzigartiges Problem ist, konnte ich keine gute Lösung finden.So wird ein genannter Unity-Registrierungstyp instanziiert
In meiner WPF-Anwendung muss ich in meinen Viewmodels einige Dienste aufrufen, um einige Daten zurückzugeben. Diese Dienste werden mit UnitOfWork injiziert, welches wiederum mit dem DbContext injiziert wird. Dieser dbcontext, der in UnitOfWork eingefügt wird, sollte basierend auf einigen Kriterien abweichen.
Ich habe Probleme, die IoC-Containerregistrierungen richtig durchzuführen und zur Laufzeit den richtigen DbContext zu injizieren. Also, wenn jemand kann bitte füllen Sie die Lücken (in der Einheit Registrierungen sowie ihre Verwendung). Ich habe einige Inline-Kommentare im folgenden Code, in denen ich Probleme habe und Hilfe brauche. Vielen Dank.
Wenn jemand meinen Registrierungscode auf die richtige Weise ersetzen und mir auch beibringen kann, wie er in meiner WPF ViewModel-Klasse verwendet wird, wäre das wirklich großartig! Vielen Dank.
Eine letzte Anmerkung: Wenn Sie in diesem Code Codierungsfehler finden, fragen Sie sich bitte nicht, wie funktioniert das überhaupt kompilieren? Der Code hier ist nicht mein richtiger Code. Um die Dinge zu vereinfachen, habe ich sie einfach aufgeschrieben. Aber es ähnelt sehr meinem echten App-Code.
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);
}
Ich würde den Aufruf an den Container in einer abstrakten Factory-Implementierung ausblenden. Es ist in Ordnung, wenn Fabriken auf den Container angewiesen sind. – Haukinger
@Haukinger: können Sie bitte einen Code einreichen, um mir zu zeigen, wie in meinem Szenario? Das würde helfen. Vielen Dank. –