这一页 http://www.postsharp.net/aspects/code-introductionPostSharp 网站上有以下预告片:
您将遇到的常见情况之一是需要在大量类上实现特定接口。这可能是INotifyPropertyChanged
, IDispose
, IEquatable
或您创建的一些自定义界面。
我想编写一个自定义方面来实现通用版本IEquatable
基于它所应用的类的属性(最好是在编译时而不是在运行时使用反射)。如果能够向简单的类添加属性,而不必每次都实现自定义方法,那就太好了。那可能吗?我希望如此,因为在本介绍中特别提到了它,但我无法找到任何示例代码。
我见过这个例子 http://www.postsharp.net/blog/post/PostSharp-Principals-Day-14-e28093-Introducing-members-and-interfaces-Part-1来自 PostSharp 网站,其中包含介绍的示例IIdentifiable
界面。但它只是返回一个GUID
这与新接口添加到的类无关。
有没有办法构造一个实现的自定义属性IEquatable
基于它所应用的类型的属性(即,如果两个实例的所有属性都相等,则使它们相等)?
我发现了使用T4模板的解决方案 https://t4ctorgenerator.codeplex.com/但想知道使用 PostSharp 是否可以实现同样的效果。
Edit:
明确地说,我希望能够写出这样的东西:
[AutoEquatable]
public class Thing
{
int Id { get; set; }
string Description { get; get; }
}
并将其自动转换为:
public class Thing
{
int Id { get; set; }
string Description { get; get; }
public override bool Equals(object other)
{
Thing o = other as Thing;
if (o == null) return false;
// generated in a loop based on the properties
if (!Id.Equals(o.Id)) return false;
if (!Description.Equals(o.Description)) return false;
return true;
}
}
使用 PostSharp 4.0 使用以下代码可以实现这一点;
[PSerializable]
class EquatableAttribute : InstanceLevelAspect, IAdviceProvider
{
public List<ILocationBinding> Fields;
[ImportMember("Equals", IsRequired = true, Order = ImportMemberOrder.BeforeIntroductions)]
public Func<object, bool> EqualsBaseMethod;
[IntroduceMember(IsVirtual = true, OverrideAction = MemberOverrideAction.OverrideOrFail)]
public new bool Equals(object other)
{
// TODO: Define a smarter way to determine if base.Equals should be invoked.
if (this.EqualsBaseMethod.Method.DeclaringType != typeof(object) )
{
if (!this.EqualsBaseMethod(other))
return false;
}
object instance = this.Instance;
foreach (ILocationBinding binding in this.Fields)
{
// The following code is inefficient because it boxes all fields. There is currently no workaround.
object thisFieldValue = binding.GetValue(ref instance, Arguments.Empty);
object otherFieldValue = binding.GetValue(ref other, Arguments.Empty);
if (!object.Equals(thisFieldValue, otherFieldValue))
return false;
}
return true;
}
// TODO: Implement GetHashCode the same way.
public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
{
Type targetType = (Type) targetElement;
FieldInfo bindingField = this.GetType().GetField("Fields");
foreach (
FieldInfo field in
targetType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic))
{
yield return new ImportLocationAdviceInstance(bindingField, new LocationInfo(field));
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)