我有以下问题。我注册我的组件并在Unity中初始化它们(例如用于控制台应用程序):
public class SharePointBootstrapper : UnityBootstrapper
{
...
public object Initialize(Type type, object parameter) =>
Container.Resolve(type,
new DependencyOverride<IClientContext>(Container.Resolve<IClientContext>(parameter.ToString())),
new DependencyOverride<ITenantRepository>(Container.Resolve<ITenantRepository>(parameter.ToString())));
public void RegisterComponents()
{
Container
.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString())
.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString())
.RegisterType<ITenantRepository, DocumentDbTenantRepository>(SharePointClientContext.Online.ToString())
.RegisterType<ITenantRepository, JsonTenantRepository>(SharePointClientContext.OnPremise.ToString());
}
}
public enum SharePointClientContext
{
Online,
OnPremise
}
class Program
{
static void Main(string[] args)
{
...
bootstrap.RegisterComponents();
var bla = bootstrap.Initialize(typeof(ISharePointManager), SharePointClientContext.Online);
}
}
因此,我使用RegisterComponents()在MVC,WCF,Console等中注册我的组件,并使用Initialize()初始化它们。
我的问题是,如果我想在运行时初始化特定的命名注册,例如,用户输入,是否可以在提供的代码(使用InjectionFactory或类似代码)时完成?
此代码工作正常,但我对其实现不满意。我觉得它可以用RegisterComponents()而不是Initialize()编写,这样它就可以接受某种类型的参数,但我不知道该怎么做。
或者,也许我的整个概念都错了?如果是这样,你会建议什么?我需要从只在运行时知道的参数解析命名注册,无论技术如何(MVC,WCF,控制台......)。
谢谢!
答案 0 :(得分:0)
我会做不同的解决方案而不是做不同的注册。
假设你需要注入IClientContext
,但是你需要不同的实现,具体取决于运行时参数。
我写了similiar answer here。您可以注入IClientContext
而不是注入IClientContextFactory
,这将负责返回正确的IClientContext
。它被称为Strategy Pattern。
public interface IClientContextFactory
{
string Context { get; } // Add context to the interface.
}
public class SharePointOnlineClientContext : IClientContextFactory
{
public string Context
{
get
{
return SharePointClientContext.Online.ToString();
}
}
}
// Factory for resolving IClientContext.
public class ClientContextFactory : IClientContextFactory
{
public IEnumerable<IClientContext> _clientContexts;
public Factory(IClientContext[] clientContexts)
{
_clientContexts = clientContexts;
}
public IClientContext GetClientContext(string parameter)
{
IClientContext clientContext = _clientContexts.FirstOrDefault(x => x.Context == parameter);
return clientContext;
}
}
将它们全部注册,就像你一样。但是注入IClientContext
而不是注入IClientContextFactor
。
还有另一种使用Func
工厂的解决方案。在this answer中查看选项3。有人可能会说这是服务定位器模式的包装器,但我会再讨论这个讨论。
public class ClientContextFactory : IClientContextFactory
{
private readonly Func<string, IClientContext> _createFunc;
public Factory(Func<string, IClientContext> createFunc)
{
_createFunc = createFunc;
}
public IClientContext CreateClientContext(string writesTo)
{
return _createFunc(writesTo);
}
}
并使用命名注册:
container.RegisterType<IClientContext, SharePointOnlineClientContext>(SharePointClientContext.Online.ToString());
container.RegisterType<IClientContext, SharePointOnPremiseClientContext>(SharePointClientContext.OnPremise.ToString());
container.RegisterType<IFactory, Factory>(
new ContainerControlledLifetimeManager(), // Or any other lifetimemanager.
new InjectionConstructor(
new Func<string, IClientContext>(
context => container.Resolve<IClientContext>(context));
用法:
public class MyService
{
public MyService(IClientContextFactory clientContextFactory)
{
_clientContextFactory = clientContextFactory;
}
public void DoStuff();
{
var myContext = SharePointClientContext.Online.ToString();
IClientContextclientContext = _clientContextFactory.CreateClientContext(myContext);
}
}