Geo*_*uer 61 c# casting c#-4.0
我想实现一个带有以下签名的方法
dynamic Cast(object obj, Type castTo);
Run Code Online (Sandbox Code Playgroud)
谁知道怎么做?obj肯定实现了castTo,但是需要正确地进行转换才能使我的应用程序的运行时绑定工作得以实现.
编辑:如果一些答案没有意义,那是因为我最初不小心输入dynamic Cast(dynamic obj, Type castTo);
- 我的意思是输入应该是object
或其他一些保证基类
Jar*_*Par 92
我认为你在这里混淆铸造和转换的问题.
通常很难知道C#中的2之间的区别,因为它们都使用相同的C#运算符:强制转换.
在这种情况下,你几乎肯定不会寻找演员表演.将a 转换dynamic
为另一个dynamic
本质上是一种身份转换.它没有提供任何价值,因为您只是将dynamic
引用返回到同一个底层对象.结果查找将没有什么不同.
相反,您在此方案中看起来想要的是转换.这是将底层对象变形为不同类型并以某种dynamic
方式访问结果对象.对此最好的API是Convert.ChangeType
.
public static dynamic Convert(dynamic source, Type dest) {
return Convert.ChangeType(source, dest);
}
Run Code Online (Sandbox Code Playgroud)
编辑
更新后的问题有以下几行:
obj肯定实现了castTo
如果是这种情况,那么该Cast
方法不需要存在.源object
可以简单地分配给dynamic
参考.
dynamic d = source;
Run Code Online (Sandbox Code Playgroud)
听起来你想要完成的是source
通过dynamic
引用在层次结构中查看特定的接口或类型.这根本不可能.生成的dynamic
引用将直接看到实现对象.它不会查看源层次结构中的任何特定类型.因此,在层次结构中转换为不同类型然后返回的想法与首先dynamic
分配给它完全相同dynamic
.它仍将指向相同的底层对象.
rse*_*nna 31
这应该工作:
public static dynamic Cast(dynamic obj, Type castTo)
{
return Convert.ChangeType(obj, castTo);
}
Run Code Online (Sandbox Code Playgroud)
编辑
我写了以下测试代码:
var x = "123";
var y = Cast(x, typeof(int));
var z = y + 7;
var w = Cast(z, typeof(string)); // w == "130"
Run Code Online (Sandbox Code Playgroud)
它类似于一种"类型转换"在PHP,JavaScript的或Python语言的一个发现(因为它也的转换价值所需的类型).我不知道这是不是一件好事,但它确实有效...... :-)
我到目前为止最好的:
dynamic DynamicCast(object entity, Type to)
{
var openCast = this.GetType().GetMethod("Cast", BindingFlags.Static | BindingFlags.NonPublic);
var closeCast = openCast.MakeGenericMethod(to);
return closeCast.Invoke(entity, new[] { entity });
}
static T Cast<T>(object entity) where T : class
{
return entity as T;
}
Run Code Online (Sandbox Code Playgroud)
开源框架Dynamitey有一个静态方法,它使用DLR进行后期绑定,包括强制转换等.
dynamic Cast(object obj, Type castTo){
return Dynamic.InvokeConvert(obj, castTo, explict:true);
}
Run Code Online (Sandbox Code Playgroud)
这比Cast<T>
使用反射调用的优势在于,这也适用于IDynamicMetaObjectProvider
具有动态转换运算符的任何运算符,即.TryConvert onDynamicObject
.
我知道已经解决了这个问题,但是我使用了不同的方法,并认为可能值得分享。另外,我觉得我的方法可能会产生不必要的开销。但是,在我们观察到的负载下,我无法观察或计算出任何糟糕的事情。我一直在寻找有关此方法的有用反馈。
使用动力学的问题是您不能将任何函数直接附加到动态对象。您必须使用一些可以计算出您不想每次都分配的作业。
在计划这个简单的解决方案时,我研究了尝试重新键入相似对象时有效的中介机构。我发现二进制数组,字符串(xml,json)或对转换进行硬编码(IConvertable)是常用的方法。由于代码的可维护性因素和惰性,我不想进行二进制转换。
我的理论是,Newtonsoft可以通过使用字符串中介程序来做到这一点。
不利的一面是,我相当确定将字符串转换为对象时,它将通过在当前程序集中搜索具有匹配属性的对象来使用反射,创建类型,然后实例化属性,这将需要更多反射。如果为true,则所有这些都可以视为可避免的开销。
C#:
//This lives in a helper class
public static ConvertDynamic<T>(dynamic data)
{
return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(data));
}
//Same helper, but in an extension class (public static class),
//but could be in a base class also.
public static ToModelList<T>(this List<dynamic> list)
{
List<T> retList = new List<T>();
foreach(dynamic d in list)
{
retList.Add(ConvertDynamic<T>(d));
}
}
Run Code Online (Sandbox Code Playgroud)
话虽如此,这适合我组合在一起的另一个实用程序,使我可以将任何对象变成动态对象。我知道我必须使用反射来正确地做到这一点:
public static dynamic ToDynamic(this object value)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
expando.Add(property.Name, property.GetValue(value));
return expando as ExpandoObject;
}
Run Code Online (Sandbox Code Playgroud)
我必须提供该功能。分配给动态类型变量的任意对象都不能转换为IDictionary,这会破坏ConvertDynamic函数。为了使用此功能链,必须为其提供动态的System.Dynamic.ExpandoObject或IDictionary <string,object>。