如何在运行时创建特定对象类型?
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();
}
}
我的所有 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();
}
}