【问题标题】:How can I create a specific object type at runtime?如何在运行时创建特定的对象类型?
【发布时间】:2015-04-24 13:02:56
【问题描述】:

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

示例代码:

public interface IExport
{
    string Exporter();
}

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

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

我想在运行时得到一个特定的类型,所以我知道我必须使用抽象工厂,但我不知道在这个例子中如何 tp。

导出由管理器类处理:

 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();
    }

提前感谢您的帮助。

【问题讨论】:

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


    【解决方案1】:

    我对 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();
            }
        }
    }
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        好吧,我终于找到了解决办法。

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

        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&lt;IExport&gt;().ToProvider&lt;ExportProvider&gt;();

        我发现的第二种可能性:

        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();
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2016-12-31
          • 1970-01-01
          • 1970-01-01
          • 2020-06-08
          • 2022-11-02
          • 2011-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多