jus*_*ase 7 c# codedom dynamic
我有一种情况,我想将LinePragmas添加到CodeDom对象.但是一些代码dom对象具有LinePragma属性,而有些则没有.
所以我想知道是否可以使用dynamic关键字来检测对象上是否存在属性(不抛出异常),如果有,则添加pragma.这是我目前的方法:
public static T SetSource<T>(this T codeObject, INode sourceNode)
where T : CodeObject
{
codeObject.UserData["Node"] = sourceNode.Source;
dynamic dynamicCodeObject = codeObject;
// How can I not throw an exception here?
if (dynamicCodeObject.LinePragma != null)
{
dynamicCodeObject.LinePragma = new CodeLinePragma(
sourceNode.Source.Path.AbsoluteUri,
sourceNode.Source.StartLine);
}
return codeObject;
}
Run Code Online (Sandbox Code Playgroud)
更新: 我使用的解决方案是添加一个名为Exists()的扩展方法.我在这里写了一篇关于它的博客文章: 成员存在动态C#4.0
jist是创建一个扩展方法,返回一个实现DynamicObject的TryGetMember的对象.它使用反射然后返回true或false.这允许你编写这样的代码:
object instance = new { Foo = "Hello World!" };
if (instance.Reflection().Exists().Foo)
{
string value = instance.Reflection().Call().Foo;
Console.WriteLine(value);
}
Run Code Online (Sandbox Code Playgroud)
您可以检测对象是否具有属性而无需使用C#4.0的动态功能 - 而是使用已经存在一段时间的反射功能(我至少知道.NET 2.0,不确定<2.0)
PropertyInfo info = codeObject.getType().GetProperty(
"LinePragma",
BindingFlags.Public | BindingFlags.Instance
)
Run Code Online (Sandbox Code Playgroud)
如果对象没有该属性,则GetProperty()将返回null.您可以对字段(GetField())和方法(GetMethod())执行类似操作.
不仅如此,一旦你拥有PropertyInfo,你可以直接使用它来做你的集合:
info.SetValue(codeObject, new CodeLinePragma(), null);
Run Code Online (Sandbox Code Playgroud)
如果您不确定该属性是否具有set方法,您可以采取更安全的路线:
MethodInfo method = info.GetSetMethod();
if(method != null)
method.Invoke(codeObject, new object[]{ new CodeLinePragma() });
Run Code Online (Sandbox Code Playgroud)
这也为您提供了额外的好处,即在动态调用的查找开销上更加高效(无法找到该语句的引用,所以我只是将它浮出去).
我想这不是直接回答你的问题,而是实现同一目标的另一种解决方案.我还没有真正使用#4.0功能(尽管我是Ruby中动态类型的忠实粉丝).它当然不像动态解决方案那样干净/可读,但如果你不想抛出异常,它可能就是这样.
编辑:正如@arbiter所指出的,"这仅对本机.net动态对象有效.例如,对于IDispatch,这不起作用."
我花了将近一个小时的时间来寻找获得某种红宝石式"RespondTo"方法的方法.肯定没有一个简单的答案,但我还没有放弃.
反思的观点应该是尝试的.
使用动态,我到目前为止唯一能做的就是将对象视为动态的扩展方法.如果它有效,它可以工作,如果没有它默默地失败...
public static void Dynamight<T>(this T target, Action<dynamic> action)
{
dynamic d = target;
try
{
action(d);
}
catch (RuntimeBinderException)
{
//That was that, didn't work out
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以......
string h = "Hello";
h.Dynamight(d => Console.WriteLine(d.Length)); //Prints out 5
h.Dynamight(d => d.Foo()); //Nothing happens
Run Code Online (Sandbox Code Playgroud)
更新:
因为我得到了downvotes和what-have-you让你比扩展方法的微妙命名更简洁:它是炸药(Geddit?)!吞噬异常并无所作为是不好的.这不是生产代码,而是概念证明的第1版.我一直忘记你不能在像stackoverflow这样的数千个论坛上微妙.Mea culpa.
归档时间: |
|
查看次数: |
3316 次 |
最近记录: |