在c#中,我可以将类型对象的变量转换为类型T的变量,其中T在类型变量中定义?


当前回答

我永远不会理解为什么你需要50个声誉才能留下评论,但我不得不说@Curt的答案正是我想要的,希望是其他人。

在我的例子中,我有一个ActionFilterAttribute,我用来更新json补丁文档的值。我不知道补丁文档的T模型是什么,我必须将其序列化并反序列化为一个普通的JsonPatchDocument,修改它,然后因为我有类型,再次将其序列化并反序列化为类型。

Type originalType = //someType that gets passed in to my constructor.

var objectAsString = JsonConvert.SerializeObject(myObjectWithAGenericType);
var plainPatchDocument = JsonConvert.DeserializeObject<JsonPatchDocument>(objectAsString);

var plainPatchDocumentAsString= JsonConvert.SerializeObject(plainPatchDocument);
var modifiedObjectWithGenericType = JsonConvert.DeserializeObject(plainPatchDocumentAsString, originalType );

其他回答

public bool TryCast<T>(ref T t, object o)
{
    if (
        o == null
        || !typeof(T).IsAssignableFrom(o.GetType())
        )
        return false;
    t = (T)o;
    return true;
}

当谈到转换为Enum类型时:

private static Enum GetEnum(Type type, int value)
    {
        if (type.IsEnum)
            if (Enum.IsDefined(type, value))
            {
                return (Enum)Enum.ToObject(type, value);
            }

        return null;
    }

你可以这样称呼它:

var enumValue = GetEnum(typeof(YourEnum), foo);

这对我来说是必要的情况下,获得几个枚举类型的描述属性值的int值:

public enum YourEnum
{
    [Description("Desc1")]
    Val1,
    [Description("Desc2")]
    Val2,
    Val3,
}

public static string GetDescriptionFromEnum(Enum value, bool inherit)
    {
        Type type = value.GetType();

        System.Reflection.MemberInfo[] memInfo = type.GetMember(value.ToString());

        if (memInfo.Length > 0)
        {
            object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), inherit);
            if (attrs.Length > 0)
                return ((DescriptionAttribute)attrs[0]).Description;
        }

        return value.ToString();
    }

然后:

string description = GetDescriptionFromEnum(GetEnum(typeof(YourEnum), foo));
string description2 = GetDescriptionFromEnum(GetEnum(typeof(YourEnum2), foo2));
string description3 = GetDescriptionFromEnum(GetEnum(typeof(YourEnum3), foo3));

或者(更好的方法),这样的类型转换可以是这样的:

 private static T GetEnum<T>(int v) where T : struct, IConvertible
    {
        if (typeof(T).IsEnum)
            if (Enum.IsDefined(typeof(T), v))
            {
                return (T)Enum.ToObject(typeof(T), v);
            }

        throw new ArgumentException(string.Format("{0} is not a valid value of {1}", v, typeof(T).Name));
    }

我永远不会理解为什么你需要50个声誉才能留下评论,但我不得不说@Curt的答案正是我想要的,希望是其他人。

在我的例子中,我有一个ActionFilterAttribute,我用来更新json补丁文档的值。我不知道补丁文档的T模型是什么,我必须将其序列化并反序列化为一个普通的JsonPatchDocument,修改它,然后因为我有类型,再次将其序列化并反序列化为类型。

Type originalType = //someType that gets passed in to my constructor.

var objectAsString = JsonConvert.SerializeObject(myObjectWithAGenericType);
var plainPatchDocument = JsonConvert.DeserializeObject<JsonPatchDocument>(objectAsString);

var plainPatchDocumentAsString= JsonConvert.SerializeObject(plainPatchDocument);
var modifiedObjectWithGenericType = JsonConvert.DeserializeObject(plainPatchDocumentAsString, originalType );

为了简单起见,将装箱和解装箱放在一边,沿着继承层次结构进行强制转换时不涉及特定的运行时操作。这主要是编译时的事情。本质上,强制转换告诉编译器将变量的值视为另一种类型。

试镜之后你能做什么?你不知道它的类型,所以你不能对它调用任何方法。你不会有什么特别的事情可以做。具体来说,只有当你在编译时知道可能的类型,手动转换它并使用if语句分别处理每个case时,它才有用:

if (type == typeof(int)) {
    int x = (int)obj;
    DoSomethingWithInt(x);
} else if (type == typeof(string)) {
    string s = (string)obj;
    DoSomethingWithString(s);
} // ...

如果需要在不知道目标类型的情况下在运行时强制转换对象,可以使用反射来生成动态转换器。

这是一个简化版本(没有缓存生成的方法):

    public static class Tool
    {
            public static object CastTo<T>(object value) where T : class
            {
                return value as T;
            }

            private static readonly MethodInfo CastToInfo = typeof (Tool).GetMethod("CastTo");

            public static object DynamicCast(object source, Type targetType)
            {
                return CastToInfo.MakeGenericMethod(new[] { targetType }).Invoke(null, new[] { source });
            }
    }

然后你可以调用它:

    var r = Tool.DynamicCast(myinstance, typeof (MyClass));