我有一个实例方法,可以创建一个新的类实例。我希望这是一个类方法。问题是我在静态方法中尝试调用GetType()时出错。是否可以将此方法转换为静态方法?
非静态字段,方法或属性' object.GetType()'
需要对象引用。
public object WithAttributes(ExpandoObject valueObject)
{
var properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.GetSetMethod() != null);
var self = Activator.CreateInstance(GetType());
var values = (IDictionary<string, object>)valueObject;
foreach (var property in properties)
{
if (values.Keys.Contains(property.Name))
{
var val = values[property.Name];
property.SetValue(self, values[property.Name]);
}
}
return self;
}
public class BaseEntity
{
public Int64 Id { get; set; }
public DateTime AddedDate { get; set; }
public DateTime ModifiedDate { get; set; }
public string IPAddress { get; set; }
public object WithAttributes(ExpandoObject valueObject)
{
// Same code as above
}
}
public class Customer : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string MobileNo { get; set; }
}
dynamic attributes = new ExpandoObject();
attributes.FirstName = "James";
attributes.LastName = "Jones";
var customer = Customer.WithAttributes(attributes);
答案 0 :(得分:1)
嗯,不幸的是,从基本抽象类型的静态方法中获取实现类型是不可能的。根据{{3}}和reed copsey's answer here。正如您在Jon的回答中所看到的,c#编译器将静态方法与其声明的类型相关联,即使它是从派生类型执行的。
这意味着你的抽象类必须知道实现它的类型,或者至少这个方法必须知道它被调用的类型。
一种方法是将WithAttributes
创建为通用方法:
public static T WithAttributes<T>((ExpandoObject valueObject)) where T: BaseEntity, new
{
// Here you can use typeOf(T)
}
这有一些优点(例如,您可以简单地编写var self = new T()
而不是使用Activator.CreateInstance()
,并且您不需要返回object
但实际类型。
但是,你不能强制调用此方法的代码传递正确的类型 - 没有什么能阻止你做这样的事情:
var customer = Customer.WithAttributes<SomeOtherBaseEntityDerivedClass>(attributes);
Jon Skeet's answer there是另一种使用泛型来解决这个问题的尝试,只有这样才能将整个抽象类创建为泛型类,所以不是public class BaseEntity
而是
public class BaseEntity<TChild>
然后您可以使用typeOf(TChild)
这与我的建议有同样的缺点(你可以轻松地public class Customer : BaseEntity<SomeOtherType>
)。
Rob Leclerc's answer here将类型作为参数提取给抽象类中的静态方法:
public static object WithAttributes(Type type, ExpandoObject valueObject)
同样,它与使用通用方法有相同的缺点,但它也有你的方法的缺点 - 它必须返回object
,你必须使用Activator.CreateInstance
。
总结 - 你要求的是不能安全地完成的 我不建议将这些方法用于公共API,但是如果您知道您的团队是唯一将继承BaseEntity的程序员,那么我可能会采用通用方法,只要您确保每个人都知道编译器可以& #39; t保护他们不要使用错误的类型参数。