我希望能够将已知类型传递给常规功能,但是我会遇到编译错误,因为我无法在设计时施放类型。
考虑我的发射功能:
示例1:
private void OnCreate<T>(T object)
{
object.CurrentDate = DateTime.Now;
object.SpecialProperty = "Hello";
}
示例2:
private void OnCreate<T>(T object)
{
object.BirthDate = DateTime.Now;
object.BirthdayMessage = "Happy Birthday";
}
我想调用ongreate并将其传递给对象。该对象恰好是MVC应用程序中的模型对象。我无法预测哪种模型对象正在传递给ongreate,但我想访问传递的模型的唯一属性。正如我的示例上面显示的那样,一个模型具有当前日期和特殊的属性。另一个有生日和生日植物。我不想为每个功能创建一个特殊功能,因为我有许多不同的模型。此外,此爆炸功能将从基类继承。这里的想法是在控制器的创建方法中提供"钩子",以便有人可以在将模型属性持续到数据库之前更改模型属性。换句话说,控制器的创建方法会将模型传递给我的ongreate函数,然后在模型传递之前将在模型上完成一些工作。
正如您期望的那样,每个模型都有不同的属性。由于此要求,我意识到我将无法提早结合并使用ongreate函数获得IntelliSense - 但我的问题是编译器不会让我参考对象的属性,直到它知道对象类型。我在设计时间无法投射它,因为我在运行时不知道类型。
编辑
我认为我的问题并不清楚,从答案来看(我对此 - 他们不是我想要的)。也许最好显示我要如何调用ongreate():
OnCreate(model);
现在,当OnCreate接收对象"模型"时,它需要能够在该模型上设置属性。我想我可以在模型上使用反射并执行这样的操作(这仅是伪代码 - 关于反射的学习):
if typeof(model) is CustomerModel then
(CustomerModel(model)).BirthDate = "1/1/1960";
(CustomerModel(model)).BirthdayMessage = "Happy Birthday";
elseif typeof(model) is AnotherModel then
(AnotherModel(model)).CurrentDate = DateTime.Now;
(AnotherModel(model)).SpecialProperty = "Hello";
etc...
,但我试图避免有一堆if/then语句。我更喜欢将呼叫"路由"到特定于通过的类型的函数。这样,打电话给on Create的电话将将对象发送到过载(?),以便不需要反射逻辑...
第二个编辑
在进一步反思(不打算双关语)后,我认为在这里,没有一堆if/其他陈述是这里的最佳方法。我提出了另一个可能效果最好的想法,并满足我表示"避免有一堆if/then语句"(在我的第一个编辑中指定的)的表达愿望:这个想法是让我的模型实现Ioncreate,这将提供。onCreate()方法。因此,可以使用我的"通用"模型对象,可以使用这种方式:
model.OnCreate();
然后,ongreate函数将知道模型上的属性:
public void OnCreate()
{
this.BirthdayMessage = "Happy Birthday";
etc...
}
我在这里只看到两个问题:
1-在控制器中,我需要测试该模型是否实现了IonCreate - 如果不是,我不会尝试调用otCreate()。2-我需要确保添加诸如OnCreate()之类的公共功能不会干扰EF6在代码优先项目中生成数据库表的方式。
我现在的问题是这种方法是最好的...还是还有其他想法要考虑...
由于 T
是任何类型,编译器不能指望它具有CurrentDate
或SpecialProperty
;您可以尝试解决这样的问题:
public interface IMyInterface {
DateTime CurrentDate {get; set}
String SpecialProperty {get; set}
}
public class MyClassA: IMyInterface {...}
public class MyClassB: IMyInterface {...}
public class MyClassC: IMyInterface {...}
...
private void OnCreate<T>(T value)
where T: IMyInterface // <- T should implement IMyInterface
{
value.CurrentDate = DateTime.Now;
value.SpecialProperty = "Hello";
}
在您的示例中,Generics
似乎不太可能是解决问题的解决方案(您的应用程序),似乎使用抽象层(Interface
或Abstract Class
)更合适。
使用"裸骨"泛型时,任何类型都可以传递给您的方法,因为任何类型的.NET属于类型Object
,您都可以在这些通用参数上执行任何相关功能。为了扩展仿制药在我们具有仿制药约束的继承层次结构中实现最基本类型的能力,这些功能使您能够限制可以作为通用参数传递的类型范围。在您的情况下,您需要使用Type Constraints
,这将类型范围限制为仅实现指定类型的类型。
例如,我们具有类型的A
,并且A
类型B
和C
作为派生类,我们希望方法M
仅接受类型键入如何实现A
:
class Program
{
static void Main(string[] args)
{
M(new A()); // will work
M(new B()); // will work
M(new C()); // will work
M(new D()); // wont work
}
public static string M<T>(T arg)
where T : A
{
return arg.Data;
}
}
public class A { public string Data { get; set; } }
public class B : A { }
public class C : B { }
public class D { }
编辑
根据您的上一次编辑,似乎您有两个解决此问题的选项。
实现抽象层(Interface
):您可能需要添加一个接口并通过模型实现。
public static void OnCreate(IBirthable arg)
{
arg.BirthDate = ...;
}
接口:
public interface IBirthable
{
DateTime BirthDate { get; set; }
string BirthdayMessage { get; set; }
}
模型:
public class CustomerModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel : IBirthable
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
使用反射:如果您选择不使用接口,则可能与模型没有逻辑连接,您可能需要使用反射。
public static void OnCreate<T>(T arg)
{
var type = arg.GetType();
var birthDateProperty = type.GetProperty("BirthDate");
if (birthDateProperty == null)
throw new ArgumentException("Argument not is implementing the model");
birthDateProperty.SetValue(arg, DateTime.Now);
//And so on...
}
模型:
public class CustomerModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}
public class AnotherModel
{
public DateTime BirthDate { get; set; }
public string BirthdayMessage { get; set; }
}