C# 基于字符串的Ninject绑定
我有一个web服务,它将处理传入的一些数据(特别是来自SharePoint文档库的InfoPath xml)。我目前正在使用Ninject处理要加载的表单数据“策略”。下面是一些代码(问题如下): Web服务(入口点) FormBStrategy与我没有列出的其他7种策略基本相同。我试图找到一种方法,将表单xml传递给Web服务,并根据即将到来的表单类型调用正确的表单反序列化 上述代码“有效”;但我感觉我在Ninject做某种服务定位,从我的阅读来看,这是一件坏事。但我想不出一个合适的方法来实现这一点。我并没有死心塌地地使用Ninject或任何IOC/DI框架C# 基于字符串的Ninject绑定,c#,ninject,C#,Ninject,我有一个web服务,它将处理传入的一些数据(特别是来自SharePoint文档库的InfoPath xml)。我目前正在使用Ninject处理要加载的表单数据“策略”。下面是一些代码(问题如下): Web服务(入口点) FormBStrategy与我没有列出的其他7种策略基本相同。我试图找到一种方法,将表单xml传递给Web服务,并根据即将到来的表单类型调用正确的表单反序列化 上述代码“有效”;但我感觉我在Ninject做某种服务定位,从我的阅读来看,这是一件坏事。但我想不出一个合适的方法来实现
是我正在做的。。。错了吗?能给我指出正确的方向吗?有两件事我不喜欢:
AddForm
方法中创建内核。这不应该发生,因为它反转了IoC模式——相反,AddForm
所属的类应该请求它所需的任何依赖项AddForm()
的使用者发送一个命名策略的字符串似乎是不对的Func
依赖项添加到拥有AddForm
的类中(称之为class X)。我在想象这样的事情:
namespace Web.Services
{
public class X
{
private readonly Func<string, IPFormDataStrategy> _strategyResolver;
public X(Func<string, IPFormDataStrategy> strategyResolver)
{
_strategyResolver = strategyResolver;
}
public bool AddForm(XmlDocument form, string formName)
{
return _strategyResolver(formName).DoWork(form);
}
}
}
你可能会发现这不必要的复杂,也许它是。。。我喜欢它,因为它使类X的依赖关系显式(即,获取给定表单名称的策略),而不是让它访问整个内核。这种方法还将策略整合到单个switch语句中。它仍然依赖于神奇的字符串,但我不知道如何绕过它,而不知道更多的上下文…服务定位器是,但重要的是要理解为什么它是一种反模式。原因通常与重构和类型安全有关。我认为判断你是否做错了事情的最好方法是将问题简化为最简单的要求,然后判断最简单的方法
据我所知,您的要求是:
在Ninject上,我不确定这是否仍然有效,但速度要快得多,我更喜欢它的语法。(如果您决定使用DI容器)如果您在示例代码中提供的类是准确的(即没有更多的方法和属性)。然后,最简单的解决方案可能会起作用,您可以摆脱许多类/对类的依赖关系 一个不依赖框架/容器的简单解决方案是:
public static class FormsProcessing
{
private static ConcurrentDictionary<string, Func<FormProcessor>> _registeredProcessors = new ConcurrentDictionary<string, Func<FormProcessor>>();
public delegate bool FormProcessor(XmlDocument form);
public static void RegisterProcessor(string formKey, Func<FormProcessor> formsProcessorFactory)
{
_registeredProcessors.AddOrUpdate(formKey, formsProcessorFactory, (k, current) => formsProcessorFactory);
}
public static FormProcessor GetProcessorFor(string formKey)
{
Func<FormProcessor> processorFactory;
if (_registeredProcessors.TryGetValue(formKey, out processorFactory);
return processorFactory();
return null;
}
public static bool Process(string formKey, XmlDocument form)
{
var processor = GetProcessorFor(formKey);
if (null == processor)
throw new Exception(string.Format("No processor for '{0}' forms available", formKey));
return processor(form);
}
}
它简单而明确,不需要或公开对IPFormDataContext
和IPFormDataStrategy
类的某些结构的任何依赖。唯一明确的依赖关系是具有FormProcessor
签名的委托
与容器类似,您需要在以下位置执行注册:
FormsProcessing.RegisterProcessor("FormA", () => new FormAStrategy().DoWork);
FormsProcessing.RegisterProcessor("FormB", () => new FormBStrategy().DoWork);
或者,通过扫描约定的程序集(例如接口签名),可以很容易地添加某种形式的(基于约定的)自动注册。这似乎是一个通用的好地方:您是否可以执行类似于
IPFormDataContext的操作,其中T:IPFormDataStrategy
来清理它?我对ninject不是很熟悉。调用web服务的应用程序是一个SharePoint列表事件处理程序。我想让事件处理程序尽可能的基本,因此是神奇的字符串。该项目的要求包括能够在未来以最小的影响添加其他表单。我可以随时更新web服务,但是升级列表事件处理程序非常痛苦。
namespace Web.Services
{
public class X
{
private readonly Func<string, IPFormDataStrategy> _strategyResolver;
public X(Func<string, IPFormDataStrategy> strategyResolver)
{
_strategyResolver = strategyResolver;
}
public bool AddForm(XmlDocument form, string formName)
{
return _strategyResolver(formName).DoWork(form);
}
}
}
public class FormsModule : NinjectModule
{
public override void Load()
{
Bind<FormAStrategy>().ToSelf();
Bind<FormBStrategy>().ToSelf();
Bind<Func<string, IPFormDataStrategy>>().ToMethod(context =>
new Func<string, IPFormDataStrategy>(formName => {
switch (formName)
{
case "FormA":
return context.Kernel.Get<FormAStrategy>();
// Note, could also simply "return new FormAStrategy()" here.
case "FormB":
return context.Kernel.Get<FormBStrategy>();
default:
throw new InvalidOperationException(formName + " is unrecognized");
}
})
);
}
}
public static class FormsProcessing
{
private static ConcurrentDictionary<string, Func<FormProcessor>> _registeredProcessors = new ConcurrentDictionary<string, Func<FormProcessor>>();
public delegate bool FormProcessor(XmlDocument form);
public static void RegisterProcessor(string formKey, Func<FormProcessor> formsProcessorFactory)
{
_registeredProcessors.AddOrUpdate(formKey, formsProcessorFactory, (k, current) => formsProcessorFactory);
}
public static FormProcessor GetProcessorFor(string formKey)
{
Func<FormProcessor> processorFactory;
if (_registeredProcessors.TryGetValue(formKey, out processorFactory);
return processorFactory();
return null;
}
public static bool Process(string formKey, XmlDocument form)
{
var processor = GetProcessorFor(formKey);
if (null == processor)
throw new Exception(string.Format("No processor for '{0}' forms available", formKey));
return processor(form);
}
}
namespace Web.Services
{
public class MyServiceClass
{
public bool AddForm(XmlDocument form, string formName)
{
return FormsProcessing.Process(formName, form);
}
}
}
FormsProcessing.RegisterProcessor("FormA", () => new FormAStrategy().DoWork);
FormsProcessing.RegisterProcessor("FormB", () => new FormBStrategy().DoWork);