I'm writing a rule based mock data generator. But to save time I've decided to use a dynamic container to store rules.
public void AddGlobalRule<T, TProperty>(Expression<Func<T, TProperty>> property, Func<Faker, dynamic, dynamic, dynamic> rule)
where T : class
{
var propertyName = ((MemberExpression)property.Body).Member.Name;
this.AddRawRule(typeof(T), rule, propertyName);
}
public void AddRawRule(Type entityType, Func<Faker, dynamic, dynamic, dynamic> rule, string propertyName)
{
if (false == this._ruleMap.ContainsKey(entityType))
{
this._ruleMap.Add(entityType, new RuleSet());
}
var ruleset = this._ruleMap.Get(entityType);
ruleset.Add((propertyName, rule));
}
The issue is that this code doesn't have intellisense, I would really like to write the function like so:
public void AddGlobalRule<T, TProperty>(Expression<Func<T, TProperty>> property, Func<Faker, T, T, TProperty> rule)
where T : class
{
var propertyName = ((MemberExpression)property.Body).Member.Name;
var dynamicRule = rule as Func<Faker, dynamic, dynamic, dynamic>;
this.AddRawRule(typeof(T), dynamicRule, propertyName);
}
Edit for clarity:
If I use Func<Faker, T, T, TProperty> rule
as the input into the function, when I use it
generator.AddGlobalRule<Employee, string>(x => x.Name,
(f, previous, current) => {
//If I use Dynamic I don't have intellisense here
return current.FirstName + current.LastName;
})
However when I try to cast the dynamic rule is null,
var dynamicRule = rule as Func<Faker, dynamic, dynamic, dynamic>;
How can I cast to the my rule, so that I can preserve intellisense?
Right. Casting to Func<Faker, dynamic, dynamic, dynamic>
is effectively the same as casting to Func<Faker, object, object, object>
, just with dynamic resolution. So you can't do that because the inputs to Func
are contravariant not covariant (a delegate that takes an arg of T
will not also accept an argument of object
).
(I'd ask yourself why you store in the map with dynamic
arguments and not just plain old object
s? Are you actually consuming these dynamically?)
Anyhow, you need to wrap your delegate in something that downcasts to the required types like:
Func<Faker, dynamic, dynamic, dynamic> dynamicRule = (a, b, c) => rule(a, (T)b, (T)c);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.