如何在运行时创建特定的对象类型?

时间:2015-04-24 13:02:56

标签: c# ninject inversion-of-control ioc-container

我有一个接口,由我的所有类实现,负责将数据导出为不同的格式。

示例代码:

public interface IExport
{
    string Exporter();
}

public class ExcelExport : IExport
{
    public string Exporter()
    {
        return "excel";
    }
}

public class PdfExport : IExport
{
    public string Exporter()
    {
        return "pdf";
    }
}

我想在运行时获得一个特定类型,所以我知道我必须使用抽象工厂,但我不知道在这个例子中是怎么回事。

导出由经理类处理:

 public interface IExportManager
{
    IExport GetExportProvider(ExportType type);
}

public interface IExportFactory
{
    IExport CreateExport(ExportType type);
}

public class ExportManager : IExportManager
{
    private IExportFactory exportFactory;

    public ExportManager(IExportFactory exportFactory)
    {
        this.exportFactory = exportFactory;
    }

    public IExport GetExportProvider(ExportType type)
    {
        return exportFactory.CreateExport(type);
    }
}

public enum ExportType
{
    PDF,
    XLSX
}

如何使用GetExportProvider方法根据类型参数获取正确的对象实例?

这是我的Ninject模块:

public class NinModule : NinjectModule
{

    public override void Load()
    {
        this.Bind<IExportFactory>().ToFactory();
        this.Bind<IExportManager>().To<ExportManager>();
        this.Bind<IExport>().To<ExcelExport>();//.WhenInjectedInto<IExportManager>().WithPropertyValue("type", ExportType.XLSX);
        this.Bind<IExport>().To<PdfExport>();//.WhenInjectedInto<IExportManager>().WithPropertyValue("type", ExportType.PDF);
    }
}

用于测试它的代码:

static void Main(string[] args)
    {
        IKernel k = new StandardKernel(new NinModule());

        IExportManager r = k.Get<IExportManager>();
        var pdf = r.GetExportProvider(ExportType.PDF);
        Console.WriteLine(pdf.Exporter());

        Console.Read();
    }

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

我对Ninject一无所知,但严格来说,从C#的角度来看,为什么不能这样做......

public class ExportFactory : IExportFactory
{
    public IExport CreateExport(ExportType type)
    {
        switch(type)
        {
            case ExportType.PDF:
                return new PdfExport();
            case ExportType.XLSX
                return new ExcelExport();
        }
    }
}

答案 1 :(得分:0)

我认为您需要在ExportFactory类中创建动态绑定。 像这样:

if (exportType == ExportType.PDF)
{
  Bind<IExport>().To<PdfExport>().InRequestScope();
}
else if (exportType == ExportType.XLSX)
{
  Bind<IExport>().To<ExcelExport>().InRequestScope();
}

答案 2 :(得分:0)

好吧,最后我得到了解决方案。

一种可能性是创建自定义提供程序:

public class ExportProvider : Provider<IExport>
    {
        protected override IExport CreateInstance(IContext context)
        {
            ExportType type = (ExportType)context.Parameters.First().GetValue(context, null);

            switch (type)
            {
                case ExportType.PDF: return new PdfExport();
                case ExportType.XLSX: return new ExcelExport();
            }

            return null;
        }
    }

并配置:this.Bind<IExport>().ToProvider<ExportProvider>();

我找到的第二种可能性:

this.Bind<IExport>().To<ExcelExport>().When((q) =>
        {
            ExportType type = (ExportType)q.Parameters.First().GetValue(new DummyContext(), null);
            return type == ExportType.XLSX;
        });

        this.Bind<IExport>().To<PdfExport>().When((q) =>
        {
            ExportType type = (ExportType)q.Parameters.First().GetValue(new DummyContext(), null);
            return type == ExportType.PDF;
        });

IParameter的GetValue要求不提供空IContext。在When子句中我们不能得到任何,但是我们可以使用不同的,因为在方法中没有检查这个参数。因此,我们可以创建一个实现IContext接口的简单类:

public class DummyContext : IContext
    {
        public Ninject.Planning.Bindings.IBinding Binding
        {
            get { throw new NotImplementedException(); }
        }

        public Type[] GenericArguments
        {
            get { throw new NotImplementedException(); }
        }

        public IProvider GetProvider()
        {
            throw new NotImplementedException();
        }

        public object GetScope()
        {
            throw new NotImplementedException();
        }

        public bool HasInferredGenericArguments
        {
            get { throw new NotImplementedException(); }
        }

        public IKernel Kernel
        {
            get { throw new NotImplementedException(); }
        }

        public ICollection<IParameter> Parameters
        {
            get { throw new NotImplementedException(); }
        }

        public Ninject.Planning.IPlan Plan
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public IRequest Request
        {
            get { throw new NotImplementedException(); }
        }

        public object Resolve()
        {
            throw new NotImplementedException();
        }
    }