将实例方法转换为类方法C#

时间:2017-09-05 13:28:40

标签: c# .net reflection

我有一个实例方法,可以创建一个新的类实例。我希望这是一个类方法。问题是我在静态方法中尝试调用GetType()时出错。是否可以将此方法转换为静态方法?

错误

  

非静态字段,方法或属性' object.GetType()'

需要对象引用。

Customer.New

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

BaseEntity.cs

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
    }
}

Customer.cs

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

1 个答案:

答案 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保护他们不要使用错误的类型参数。