当你没有';我不知道是什么类型的

本文关键字:我不知道 是什么 类型 当你 | 更新日期: 2023-09-27 18:23:48

我的BusinessObject类有这样的扩展方法:

public static class Extensions
{
    public static T Clone<T>(this T obj)
        where T: BusinessObject<T>, new()
    {
        T newObj = new T();
        var props = newObj.Properties;
        foreach (var p in props)
            newObj.Properties[p.Name].SetValue(newObj, obj.Properties[p.Name].GetValue(obj));
        return newObj;
    }
}

该方法的内容非常有效,但我有一个非泛型BusinessObject类和一个泛型对应类。我的很多代码都在非泛型变量中传递对象的泛型版本的实例(请不要问我20个关于为什么的问题)。到目前为止,我还没有遇到任何问题,因为当我调用这个扩展方法时,它需要一个通用版本。

调用Clone方法的代码使用BusinessObject变量,该变量包含BusinessObject变量的实例。如何将变量强制转换为实际值?换句话说:

Customer cust = new Customer();   // Customer derives from BusinessObject<Customer>
var CustomerClone = cust.Clone(); // This works
BusinessObject obj = cust;
var clone = obj.Clone(); // This doesn't work

当然,在这个例子中,我知道"obj"是一个Customer,但在我的实际方法中,我不知道这一点,因为它可以是任何数量的派生类型。我只需使用GetType()就可以很容易地找到派生类型,但如何在运行时将变量强制转换为该类型呢?

当你没有';我不知道是什么类型的

在您的情况下,我会说"失去T"-您没有用它来做任何其他方式无法做的重要事情(例如Activator.CreateInstance)。您可以提供两个API——一个是通用的,一个是非通用的,以便进行方便的强制转换。例如:

BusinessObject newObj = (BusinessObject)Activator.CreateInstance(obj.GetType());

这也是非常关键的,因为您想要的T实际上不是声明T,而是具体的T。意思是:如果你有一个SuperCustomer : Customer,但把它放在Customer变量中,然后调用Clone,你想得到一个新的SuperCustomer。然而,T将是Customer。使用GetType()将更加可靠。

这里的另一个有用技巧是dynamic,这是一种从非泛型转换为泛型的巧妙方法。考虑:

dynamic foo = 123;
Bar(foo);
void Bar<T>(T bar) {
   Console.WriteLine(typeof(T));
}

将写入CCD_ 14。尽管在编译器中只真正了解objectdynamic主要实现为object,带有一些奇特的位),但它已经在运行中切换到了正确的T

然而,要强调的是,我不会在这里使用这个:我只会有:

public static BusinessObject Clone(this BusinessObject obj)
{
    BusinessObject newObj = (BusinessObject)
          Activator.CreateInstance(obj.GetType());
    var props = newObj.Properties;
    foreach (var p in props)
        newObj.Properties[p.Name].SetValue(newObj,
          obj.Properties[p.Name].GetValue(obj));
    return newObj;
}

如果我真的需要泛型的话,使用dynamic作为我的后备策略。

相关文章: