基于字符串的Ninject绑定

Sli*_*ish 7 c# ninject

我有一个Web服务,它将传递一些数据(特别是来自SharePoint文档库的InfoPath xml).我目前正在使用Ninject来处理要加载的数据"策略".这是一些代码(问题如下):

网络服务(入口点)

namespace Web.Services
{
    public bool AddForm(XmlDocument form, string formName)
    {
        IKernel kernel = new StandardKernel(new FormsModule());
        var ctx = kernel.Get<IPFormDataContext>(formName);

        return ctx.DoWork(form);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ninject相关事物

namespace Core.Modules
{
    public class FormsModule : NinjectModule
    {
        public override void Load()
        {
            Bind<IPFormDataContext>().ToSelf().Named("FormA");
            Bind<IPFormDataContext>().ToSelf().Named("FormB");
            // Snip

            Bind<IPFormDataStrategy>().To<FormAStratgey>()
                .WhenParentNamed("FormA");
            Bind<IPFormDataStrategy>().To<FormBStrategy>()
                .WhenParentNamed("FormB");
            // Snip
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

模式相关的事情

namespace Core.Forms
{
    public class IPFormDataContext
    {
        private IPFormDataStrategy _ipFormDataStrategy;

        public IPFormDataContext(IPFormDataStrategy strategy)
        {
            _ipFormDataStrategy = strategy;
        }

        public bool DoWork(XmlDocument form)
        {
            return _ipFormDataStrategy.DoWork(form);
        }
    }

    public abstract class IPFormDataStrategy
    {
        public abstract bool DoWork(XmlDocument form);
    }
}

namespace Core.Forms.FormStrategies
{
    class FormAStrategy : IPFormDataStrategy
    {
        public override bool DoWork(XmlDocument form)
        {
            // Deserialize form using (xsd.exe generated) FormAData
            // and perform some operation on the resulting data.
            return resultOfWork;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

FormBStrategy和我没有列出的其他7个策略大致相同.我正在尝试找到一种方法将表单xml传递给webservice并根据正在进入的表单类型调用正确的表单反序列化.

上面的代码"有效"; 但感觉我在Ninject做了某种服务,从我正在阅读的内容来看是件坏事.但我想不出一个正确的方法来实现这一目标.我并没有决定使用Ninject或任何IOC/DI框架.

我正在做什么......错了?我可以指出正确的方向吗?

Ale*_*lex 3

如果您在示例代码中提供的类是准确的(即没有更多的方法和属性)。那么最简单的解决方案可能会起作用,并且您可以摆脱许多类/类的依赖关系。

一个不依赖框架/容器的简单解决方案是:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

namespace Web.Services
{
    public class MyServiceClass
    {
        public bool AddForm(XmlDocument form, string formName)
        {
            return FormsProcessing.Process(formName, form);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它简单而明确,不需要或公开对IPFormDataContextIPFormDataStrategy类的某些结构的任何依赖。您拥有的唯一显式依赖项是具有FormProcessor签名的委托。

与容器类似,您需要在某处执行注册:

FormsProcessing.RegisterProcessor("FormA", () => new FormAStrategy().DoWork);
FormsProcessing.RegisterProcessor("FormB", () => new FormBStrategy().DoWork);
Run Code Online (Sandbox Code Playgroud)

或者,通过扫描程序集的约定(例如接口签名)来添加某种形式的(基于约定的)自动注册也很容易。