Mat*_*ell 21 c# vb.net delegates
我正在尝试创建一个委托(作为测试):
Public Overridable ReadOnly Property PropertyName() As String
Run Code Online (Sandbox Code Playgroud)
我的直觉尝试是声明代表这样:
Public Delegate Function Test() As String
Run Code Online (Sandbox Code Playgroud)
并实例化如下:
Dim t As Test = AddressOf e.PropertyName
Run Code Online (Sandbox Code Playgroud)
但这会引发错误:
方法'Public Overridable ReadOnly Property PropertyName()As String'没有与委托'Delegate Function Test()As String'兼容的签名.
因为我正在处理一个属性我试过这个:
Public Delegate Property Test() As String
Run Code Online (Sandbox Code Playgroud)
但这会引发编译错误.
所以问题是,我如何为一个财产代表?
看到这个链接:
Mar*_*ell 37
使用AddressOf解决问题 - 如果你在编译时知道prop-name,你可以(至少在C#中)使用anon-method/lambda:
Test t = delegate { return e.PropertyName; }; // C# 2.0
Test t = () => e.PropertyName; // C# 3.0
Run Code Online (Sandbox Code Playgroud)
我不是VB专家,但反射器声称这与以下相同:
Dim t As Test = Function
Return e.PropertyName
End Function
Run Code Online (Sandbox Code Playgroud)
那样有用吗?
原始答案:
您可以为属性创建委托Delegate.CreateDelegate; 这可以打开任何类型的实例,固定为单个实例 - 并且可以用于getter或setter; 我将在C#中给出一个例子......
using System;
using System.Reflection;
class Foo
{
public string Bar { get; set; }
}
class Program
{
static void Main()
{
PropertyInfo prop = typeof(Foo).GetProperty("Bar");
Foo foo = new Foo();
// create an open "getter" delegate
Func<Foo, string> getForAnyFoo = (Func<Foo, string>)
Delegate.CreateDelegate(typeof(Func<Foo, string>), null,
prop.GetGetMethod());
Func<string> getForFixedFoo = (Func<string>)
Delegate.CreateDelegate(typeof(Func<string>), foo,
prop.GetGetMethod());
Action<Foo,string> setForAnyFoo = (Action<Foo,string>)
Delegate.CreateDelegate(typeof(Action<Foo, string>), null,
prop.GetSetMethod());
Action<string> setForFixedFoo = (Action<string>)
Delegate.CreateDelegate(typeof(Action<string>), foo,
prop.GetSetMethod());
setForAnyFoo(foo, "abc");
Console.WriteLine(getForAnyFoo(foo));
setForFixedFoo("def");
Console.WriteLine(getForFixedFoo());
}
}
Run Code Online (Sandbox Code Playgroud)
小智 11
我只是创建了一个具有相当好性能的帮助器:http: //thibaud60.blogspot.com/2010/10/fast-property-accessor-without-dynamic.html 它不使用IL/Emit方法,它非常快!
由oscilatingcretin编辑2015/10/23
来源包含一些套管问题和特殊的=""必须删除.在链接腐烂之前,我想我会发布一个清理版本的源码,以便轻松复制意大利面,以及如何使用它的示例.
修改来源
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
namespace Tools.Reflection
{
public interface IPropertyAccessor
{
PropertyInfo PropertyInfo { get; }
object GetValue(object source);
void SetValue(object source, object value);
}
public static class PropertyInfoHelper
{
private static ConcurrentDictionary<PropertyInfo, IPropertyAccessor> _cache =
new ConcurrentDictionary<PropertyInfo, IPropertyAccessor>();
public static IPropertyAccessor GetAccessor(PropertyInfo propertyInfo)
{
IPropertyAccessor result = null;
if (!_cache.TryGetValue(propertyInfo, out result))
{
result = CreateAccessor(propertyInfo);
_cache.TryAdd(propertyInfo, result); ;
}
return result;
}
public static IPropertyAccessor CreateAccessor(PropertyInfo PropertyInfo)
{
var GenType = typeof(PropertyWrapper<,>)
.MakeGenericType(PropertyInfo.DeclaringType, PropertyInfo.PropertyType);
return (IPropertyAccessor)Activator.CreateInstance(GenType, PropertyInfo);
}
}
internal class PropertyWrapper<TObject, TValue> : IPropertyAccessor where TObject : class
{
private Func<TObject, TValue> Getter;
private Action<TObject, TValue> Setter;
public PropertyWrapper(PropertyInfo PropertyInfo)
{
this.PropertyInfo = PropertyInfo;
MethodInfo GetterInfo = PropertyInfo.GetGetMethod(true);
MethodInfo SetterInfo = PropertyInfo.GetSetMethod(true);
Getter = (Func<TObject, TValue>)Delegate.CreateDelegate
(typeof(Func<TObject, TValue>), GetterInfo);
Setter = (Action<TObject, TValue>)Delegate.CreateDelegate
(typeof(Action<TObject, TValue>), SetterInfo);
}
object IPropertyAccessor.GetValue(object source)
{
return Getter(source as TObject);
}
void IPropertyAccessor.SetValue(object source, object value)
{
Setter(source as TObject, (TValue)value);
}
public PropertyInfo PropertyInfo { get; private set; }
}
}
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
public class MyClass
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
MyClass e = new MyClass();
IPropertyAccessor[] Accessors = e.GetType().GetProperties()
.Select(pi => PropertyInfoHelper.CreateAccessor(pi)).ToArray();
foreach (var Accessor in Accessors)
{
Type pt = Accessor.PropertyInfo.PropertyType;
if (pt == typeof(string))
Accessor.SetValue(e, Guid.NewGuid().ToString("n").Substring(0, 9));
else if (pt == typeof(int))
Accessor.SetValue(e, new Random().Next(0, int.MaxValue));
Console.WriteLine(string.Format("{0}:{1}",
Accessor.PropertyInfo.Name, Accessor.GetValue(e)));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
40826 次 |
| 最近记录: |