Is it possible to have an array of unknown types?
public static bool Compare<T>(this T source, T other, params Expression<Func<T>>[] propertiesToSkip)
{
PropertyInfo[] sourceProperties = source.GetType().GetProperties();
List<string> lstPropertiesToSkip = (from x in propertiesToSkip select ((MemberExpression)((UnaryExpression)x.Body).Operand).Member.Name).ToList();
return !(sourceProperties.Any(sourcePropertyInfo => !lstPropertiesToSkip.Contains(sourcePropertyInfo.Name) && (!sourcePropertyInfo.GetValue(source, null).Equals(sourcePropertyInfo.GetValue(other, null)))));
}
I want to be able to call this function by.
var source = new MyClass();
var other = new MyClass();
source.Compare<MyCl开发者_StackOverflow中文版ass>(other, ()=>SkipProperty1, ()=>SkipProperty2);
The problem is ()=>SkipProperty1 and ()=>SkipProperty2 are not of type MyClass. I need:
Compare <A,B,C,D...>
params Expression<Func<T>>[] where T is A,B,C,D,E...
I have looked at AutoMapper, with fluent syntax.
public IMappingExpression<TSource, TDestination> ForMember(string name, Action<IMemberConfigurationExpression<TSource>> memberOptions);
Mapper.CreateMap<MyClass, MyClass>()
.ForMember(dest => dest.Property1, opt => opt.Ignore())
.ForMember(dest => dest.Property2, opt => opt.Ignore()));
- Can I change the signature of Compare to make the function work?
- Is there other way to solving this? For example using fluent syntax
Note I don't want to send property names as strings.
One option would be to change the signature of your param
arguments to be lambda expressions that return object
. Something like this:
public static bool Compare<T>
(this T source, T other, params Expression<Func<object>>[] propertiesToSkip)
This should work fine, because any .NET type can be cast or boxed to object. You'll need to slightly adjust your code to extract PropertyInfo
from the lambda expressions (because there will be additional boxing or cast).
Using fluent syntax should work as well. You'll need some type to pass around:
class SkipComparison<T> {
public T Source { get; set; }
public T Other { get; set; }
public List<PropertyInfo> PropertiesToSkip { get; set; }
public SkipComparison<T> Skip<R>(Expression<Func<R>> f)
// TODO: Extract property info, add it to
// 'PropertiesToSkip' and 'return this;'
public bool Run()
// TODO: Actually perform the comparison here
}
Your Compare
method will return a new instance of this class with just Source
and Other
set and you'll use the Skip
method to add additional properties to be skipped.
精彩评论