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

How can I create a specific object type at runtime?

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

示例代码:

public interface IExport
{
    string Exporter();
}

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

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

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

导出由经理处理class:

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

在此先感谢您的帮助。

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

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

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

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

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

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 子句中我们无法获取任何参数,但我们可以使用不同的参数,因为该参数在方法中并未像看起来那样被选中。所以我们可以创建一个简单的 class 来实现 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();
        }
    }