Consider an interface like this:
new Provider().For(myClass).ExcludeProperties("Height", "Width");
public IEditableStateProvider For(object target) {...}
public IEditableStateProvider ExcludePropertyNames(params string[] propertyNames) {...}
I want to replace the params string[] propertyNames arg with params Expression<Func<object>>[] propertyNames so that I would instead have the following.
new Provider().For(myClass).ExcludeProperties(()=>Height, ()=>Width);
I have seen code similar to this so I think it should work, but I am not getting it yet. How can I get this to work?
EDIT - doing this without Generics
Here is some code from an open source project I was looking at where type inference is working without any generics. I was looking to do the same but I don't see where the type inference is coming from (I do see it working though!)
// USAGE (here this is being called from code-behind of a WPF window
private void TrackSelectedTab() {
Services.Tracker.Configure(tabControl)
.AddProperties(() => tabControl.SelectedIndex);
Services.Tracker.ApplyState(tabControl);
}
private void TrackMainWindow() {
Services.Tracker.Configure(this)
.AddProperties(
() => Height,
() => Width,
() => Left,
() => Top,
() => WindowState)
.SetKey("MainWindow")
.SetMode(PersistModes.Automatic);
Services.Tracker.ApplyState(this);
}
// Collab classes
public class SettingsTracker
{
public TrackingConfiguration Configure(object target) {
...
return config;
}
}
public class TrackingConfiguration
{
public TrackingConfiguration AddProperties(params Expression<Func<object>>[] properties) {
...
return this;
}
}
static class Services
{
public static readonly SettingsTracker Tracker = new SettingsTracker(ObjectStore);
}
You should create a generic Provider class in addittion to a non-generic one, so you can take advantage of type inference and type safety:
Interface:
interface IEditableStateProvider<T>
{
IEditableStateProvider<T> For(T target);
IEditableStateProvider<T> ExcludePropertyNames(params Expression<Func<T, object>>[] excludedProperties);
}
Dummy implementation:
class Provider<T> : IEditableStateProvider<T>
{
public IEditableStateProvider<T> For(T target)
{
// dummy
return this;
}
public IEditableStateProvider<T> ExcludePropertyNames(params Expression<Func<T, object>>[] excludedProperties)
{
// dummy
return this;
}
}
class Provider
{
// generic factory method to make use of type inference
public static IEditableStateProvider<T> For<T>(T obj)
{
return new Provider<T>().For(obj);
}
}
Usage:
var myClass = new List<object>(); // or whatever
Provider.For(myClass).ExcludePropertyNames(x => x.Count);
The type T is now infered when you call .For(myClass), and you can now access the properties of type T in a type safe manner via a lambda when calling ExcludePropertyNames.
If you really want a non-generic version:
interface IEditableStateProvider
{
IEditableStateProvider For(object target);
IEditableStateProvider ExcludePropertyNames(params Expression<Func<object>>[] excludedProperties);
}
class Provider : IEditableStateProvider
{
public IEditableStateProvider For(object target)
{
// dummy
return this;
}
public IEditableStateProvider ExcludePropertyNames(params Expression<Func<object>>[] excludedProperties)
{
// dummy
return this;
}
}
var myClass = new List<object>();
new Provider().For(myClass).ExcludePropertyNames(() => myClass.Count);
but please note my comment below.
Related
What I want to do is to define one or more Setup(s) to one Return call on multiple method calls of the mocked object; hence avoiding multiple single calls to do Setup().Return()s.
The compiler provides an error when attempting the following which demonstrates the goal, so this is not an appropriate way to achieve that goal.
var mPlatform = new Mock<IPlatformCommunicator>();
mPlatform.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()))
.Setup(mp => mp.Start(It.IsAny<Action<IStatus>>()))
...
.Returns(mockStatusIndeterminate.Object as IStatus);
Is there way to define multiple method calls in Setup to economize the total lines of code?
This is not an option too:
.Setup(mp => mp.PreStart(It.IsAny<Action<IStatus>>()) || mp.Start(It.IsAny<Action<IStatus>>()))
As #Nkosi mentions, not really. But there are options that may work depending on your usage.
SetReturnsDefault
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.SetReturnsDefault<string>("This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
Any method that returns a string will return whatever you specify.
The default value provider is similar but across the board.
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.DefaultValueProvider = new MyDefaultValueProvider();
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public class MyDefaultValueProvider : DefaultValueProvider
{
protected override object GetDefaultValue(Type type, Mock mock)
{
return "This is my default value";
}
}
Create your own extension; the following is a working mvp
void Main()
{
var fooMock = new Mock<IFoo>();
fooMock.Setup(new Expression<Func<IFoo, string>>[] { x => x.Bar(), x => x.Baz() }, "This is a mocked value");
var foo = fooMock.Object;
Console.WriteLine($"foo.Bar(): {foo.Bar()}");
Console.WriteLine($"foo.Baz(): {foo.Baz()}");
}
public interface IFoo
{
string Bar();
string Baz();
}
public static class MoqExtensions
{
public static Mock<T> Setup<T, U>(this Mock<T> self, Expression<Func<T, U>>[] setups, U returns)
where T : class
{
foreach (var setup in setups)
{
self.Setup(setup).Returns(returns);
}
return self;
}
}
All of the above produce the following result
You could create your own extension method on Mock<T> that does what you want:
public static class MoqExt {
public static void SetupReturnOnAll<T, TResult>(
this Mock<T> mock,
TResult returnValue,
params Expression<Func<T, TResult>>[] expressions)
where T: class {
foreach (var expr in expressions)
mock.Setup(expr).Returns(returnValue);
}
}
Usage looks like this:
mPlatform
.SetupReturnOnAll(
mockStatusIndeterminate.Object as IStatus,
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()));
With some extra effort to could improve the interface to this:
mPlatform
.SetupAll(
mp => mp.PreStart(It.IsAny<Action<IStatus>>()),
mp => mp.Start(It.IsAny<Action<IStatus>>()))
.Return(mockStatusIndeterminate.Object as IStatus);
For that you'll need an extra class though:
public class MultiSetup<T, TResult>
where T: class {
public Mock<T> Mock { get; }
public Expression<Func<T, TResult>>[] Expressions { get; }
public MultiSetup(Mock<T> mock, Expression<Func<T, TResult>>[] expressions)
=> (Mock, Expressions) = (mock, expressions);
public void Return(TResult returnValue) {
foreach (var expr in Expressions)
Mock.Setup(expr).Returns(returnValue);
}
}
And you'd create it with this extension:
public static class MoqExt {
public static MultiSetup<T, TResult> SetupAll<T, TResult>(
this Mock<T> mock,
params Expression<Func<T, TResult>>[] expressions)
where T : class
=> new MultiSetup<T, TResult>(mock, expressions);
}
I have the following class structure
public abstract class SalesTransaction
{
}
public class Invoice : SalesTransaction
{
}
public class Estimate : SalesTransaction
{
}
public interface IRepostory<T>
{
T First(Expression<Func<T, bool>> predicate);
void Add(T item);
T Single(Expression<Func<T, bool>> predicate, bool disableTracking = false);
}
Can I somehow abstract IRepository<Invoice> and IRepository<Estimate> by casting it to IRepository<SalesTransaction>?
IRepository<Invoice> invoiceRepository = /* Create instance */;
IRepository<SalesTransaction> salesTransaction = invoiceRepository;
The code above doesn't compile. Is there a workaround to get it to compile and work?
You could create a SalesTransaction repository as wrapper around repositories of more specific types. (Shown here for invoices)
public class InvoiceAsSalesTransactionRepository : IRepostory<SalesTransaction>
{
private readonly IRepostory<Invoice> _invoiceRepository = new InvoiceRepository();
public void Add(SalesTransaction item)
{
if (item is Invoice invoice) {
_invoiceRepository.Add(invoice);
} else {
throw new ArgumentException("Item must be Invoice");
}
}
public SalesTransaction First(Expression<Func<SalesTransaction, bool>> predicate)
{
return _invoiceRepository.First(ToInvoicePredicate(predicate));
}
public SalesTransaction Single(Expression<Func<SalesTransaction, bool>> predicate,
bool disableTracking = false)
{
return _invoiceRepository.Single(ToInvoicePredicate(predicate), disableTracking);
}
private static Expression<Func<Invoice, bool>> ToInvoicePredicate(
Expression<Func<SalesTransaction, bool>> predicate)
{
var param = Expression.Parameter(typeof(Invoice), predicate.Parameters[0].Name);
return Expression.Lambda<Func<Invoice, bool>>(predicate.Body, param);
}
}
As you can see, you need some Reflection magic to convert the predicate type. Therefore, you cannot simply cast your repositories. Note that we don't need to cast anything here, since a valid SalesTansaction predicate is always a valid Invoice predicate, as SalesTansactions contain only properties also available in Invoices.
I'm starting with generics types and I'm stuck with my project. Maybe I did not understand generics very well. Explanations have been inserted inline. Basically I need to implement the Do() method but I don't know how to resolve <T2>:
public abstract class MyGenericClass<T> { }
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression;
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
// I need to mantain a list of my generic class for later use.
// I don't know T2 at this point.
// So I Chose to use Inheritance as a workaround (MyGenericClass<T> and MyGenericClass<T, T2>).
// Maybe it's not a good solution but I counldn't find out other solution.
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
// I receive the parametric argument T2 here as part of an Expresion.
// And I keep the expression in my list.
public MyGenericClass<T, T2> ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client<T>
{
MyClass<T> class1;
// class1 has been created and his field MyGenericList has been populated.
// Then when I call Do()....
public void Do()
{
foreach (var item in class1.MyGenericList)
{
// I need something like this here,
// but it does not compile because I don't know T2 here.
// The caller of Do() method doesn't know T2.
MyGenericClass<T, T2> myGenericItem = (MyGenericClass<T, T2>)item;
var a = myGenericItem.expression;
}
}
}
You have to give Do() the T2 parameter somehow. So my solution is to create a method parameter of the same type. I also nested the types in order to make sure all of them refer to the same T.
I also renamed the parameters to be more descriptive
// T -> TArg
// T2 -> TResult
public abstract class MyBaseClass<TArg>
{
public class MyExpressionClass<TResult> : MyBaseClass<TArg>
{
public Expression<Func<TArg, TResult>> Expression { get; private set; }
public MyExpressionClass(Expression<Func<TArg, TResult>> expression)
{
this.Expression=expression;
}
}
public class MyCollectionClass
{
public List<MyBaseClass<TArg>> MyGenericList = new List<MyBaseClass<TArg>>();
public MyExpressionClass<TResult> ReceivingMethod<TResult>(Expression<Func<TArg, TResult>> expression)
{
var genericImp = new MyExpressionClass<TResult>(expression);
MyGenericList.Add(genericImp);
return genericImp;
}
}
public class Client
{
public MyCollectionClass List = new MyCollectionClass();
public void Do<TResult>()
{
foreach(var item in List.MyGenericList)
{
var expr = item as MyExpressionClass<TResult>;
if(expr!=null)
{
var a = expr.Expression;
Console.WriteLine(a);
}
}
}
}
}
class Program
{
static void Main(string[] args)
{
var client = new MyBaseClass<int>.Client();
// add conversion expressions
client.List.ReceivingMethod((i) => (i).ToString());
client.List.ReceivingMethod((i) => (2*i).ToString());
client.List.ReceivingMethod((i) => (3*i).ToString());
// The programmer has to manually enforce the `string` type
// below based on the results of the expressions above. There
// is no way to enforce consistency because `TResult` can be
// _any_ type.
client.Do<string>();
// Produces the following output
//
// i => i.ToString()
// i => (2*i).ToString()
// i => (3*i).ToString()
}
}
Solution 1 Inspired from #KMoussa comment. I've delegate the responsability to MyGenericClass using an abstract method. This seems a better design. All subclasses will implement this method DoTheWork(). And can be invoked from my Client.Do() method with only T param:
public abstract class MyGenericClass<T>
{
public abstract string DoTheWork();
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public override string DoTheWork()
{
// I can use expression here
}
private Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
// I don't need to cast to MyGenericClass<T, T2>
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
string result = myGenericItem.DoTheWork();
}
}
}
Solution 2 Inspired from #ja72 and #juharr comments. Using reflection. First I save the type T2 on MyGenericClass using an abstract property. Then I can invoke a generic method MethodWithArgument using reflection so I can introduce the parameter for the casting:
public abstract class MyGenericClass<T>
{
public abstract Type type { get; set; }
}
public class MyGenericClass<T, T2> : MyGenericClass<T>
{
public Expression<Func<T, T2>> expression { get; set; }
public MyGenericClass(Expression<Func<T, T2>> expression)
{
type = typeof(T2); // I save the type of T2
this.expression = expression;
}
}
public class MyClass<T>
{
public List<MyGenericClass<T>> MyGenericList = new List<MyGenericClass<T>>();
public void ReceivingMethod<T2>(Expression<Func<T, T2>> expression)
{
MyGenericClass<T, T2> genericImp = new MyGenericClass<T, T2>(expression);
}
}
public class Client<T>
{
MyClass<T> class1;
public void Do()
{
foreach (MyGenericClass<T> myGenericItem in class1.MyGenericList)
{
MethodInfo method = GetType().GetMethod("MethodWithArgument");
MethodInfo generic = method.MakeGenericMethod(new Type[] { myGenericItem.type });
string g = (string)generic.Invoke(this, new object[] { myGenericItem });
}
}
// I introduce T2 in this method
public string MethodWithArgument<T2>(MyGenericClass<T> myClass)
{
// Now, the casting is valid
MyGenericClass<T, T2> mySubClass = (MyGenericClass<T, T2>)myClass;
var a = mySubClass.expression;
// I can work with expression here
}
}
I am trying to create an extension method to list the properties in the lambda expression.
Let say there is a Class named Example
public class Example {
Public string Name {get;set;}
Public string Description {get;set;}
}
the extension method can be something like below
public static void GetProperties<T>(this T obj) where T : new()
{
}
Expected usage : this.GetProperties<Example>(m=>m.
so when i type m=>m. should display both the properties (Name,Description).
I think you need to used Func:
public static void GetProperties<T, V>(this T obj, Func<T, V selector) where T : new()
{
}
Usage:
Example ex = new Example();
ex.GetProperties(m => m.Name); // Func<Example, string>
ex.GetProperties(m => m.Description); // Func<Example, string>
I really didn't understand the expected behavior inside the method. But you mentioned m.Name and m.Description. So a property selector is your way.
Func<Example, string> is a function that accepts an Example input parameter and returns a string (which is the property in case of Name and Description).
public static class PropertyUtility
{
public static string GetPropertyName<T>(this T entity, Expression<Func<T, object>> exp)
{
if (exp.Body is MemberExpression) {
return ((MemberExpression)exp.Body).Member.Name;
}
else {
var op = ((UnaryExpression)exp.Body).Operand;
return ((MemberExpression)op).Member.Name;
}
}
}
And use like this:
Example ex = new Example();
var property = ex.GetPropertyName(x => x.Description);
In my project I need to transform data between several classes so I created a class DataMapper that is used for strong-typed mapping of properties from two different classes. When properties in the pair need to be modified I store two delegates (converters) for this purpose.
Then the DataMapper has two methods Update(T source, S target) and Update(S source, T target) that use these mappings to provide the tranformation.
public class DataMapper<TSourceType, TTargetType> : IDataUpdater<TSourceType, TTargetType> {
private readonly IDictionary<PropertyInfo, PropertyInfo> _sourceToTargetMap = new Dictionary<PropertyInfo, PropertyInfo>();
private readonly IDictionary<PropertyInfo, object> _converters = new Dictionary<PropertyInfo, object>();
public DataMapper<TSourceType, TTargetType> Map<TSourceValue, TTargetValue>(
Expression<Func<TSourceType, TSourceValue>> sourcePropExpr,
Expression<Func<TTargetType, TTargetValue>> targetPropExpr)
{
_sourceToTargetMap.Add(sourcePropExpr.AsPropertyInfo(), targetPropExpr.AsPropertyInfo());
return this;
}
public DataMapper<TSourceType, TTargetType> Map<TSourceValue, TTargetValue>(
Expression<Func<TSourceType, TSourceValue>> sourcePropExpr,
Expression<Func<TTargetType, TTargetValue>> targetPropExpr,
Func<TSourceValue, TTargetValue> sourceToTargetConverter,
Func<TTargetValue, TSourceValue> targetToSourceConverter)
{
_sourceToTargetMap.Add(sourcePropExpr.AsPropertyInfo(), targetPropExpr.AsPropertyInfo());
_converters.Add(sourcePropExpr.AsPropertyInfo(), sourceToTargetConverter);
_converters.Add(targetPropExpr.AsPropertyInfo(), targetToSourceConverter);
return this;
}
public void Update(TSourceType source, TTargetType target) {
foreach (var keyValuePair in _sourceToTargetMap) {
var sourceProp = keyValuePair.Key;
var targetProp = keyValuePair.Value;
Update(source, target, sourceProp, targetProp);
}
}
public void Update(TTargetType source, TSourceType target) {
foreach (var keyValuePair in _sourceToTargetMap) {
var sourceProp = keyValuePair.Value;
var targetProp = keyValuePair.Key;
Update(source, target, sourceProp, targetProp);
}
}
private void Update(
object source,
object target,
PropertyInfo sourceProperty,
PropertyInfo targetProperty)
{
var sourceValue = sourceProperty.GetValue(source);
if (_converters.ContainsKey(sourceProperty)) {
sourceValue = typeof(InvokeHelper<,>)
.MakeGenericType(sourceProperty.PropertyType, targetProperty.PropertyType)
.InvokeMember("Call", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, new[] { _converters[sourceProperty], sourceValue });
}
targetProperty.SetValue(target, sourceValue);
}
}
Here is the usage:
public SomeClass {
private static readonly IDataUpdater<SomeClass, SomeOtherClass> _dataMapper = new DataMapper<SomeClass, SomeOtherClass>()
.Map(x => x.PropertyA, y => y.PropertyAA)
.Map(x => x.PropertyB, y => y.PropertyBB, x => Helper.Encrypt(x), y => Helper.Decrypt(y));
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public void LoadFrom(SomeOtherClass source) {
_dataMapper.Update(source, this);
}
public void SaveTo(SomeOtherClass target) {
_dataMapper.Update(this, target);
}
}
You can see in class DataHelper in the last overload of method Update that when I want to call the stored converter function, I use helper class InvokeHelper, because I didn't found other way how to call boxed delegate Func. Code for class InvokeHelper is simple - just single static method:
public static class InvokeHelper<TSource, TTarget> {
public static TTarget Call(Func<TSource, TTarget> converter, TSource source) {
return converter(source);
}
}
Is there a way how to do it without reflection? I need to optimalize these transformations for speed.
Thanks.
You can use Delegate.DynamicInvoke to invoke the delegate. Or, use dynamic:
((dynamic)(Delegate)_converters[sourceProperty])(sourceValue);
The (Delegate) cast is not necessary. It's for documentation and runtime assertion purposes. Leave it out if you don't like it.
Actually, you better use delegate instead of object in the dictionary.
If it were me, I would use a little meta-coding with expressions to create a list of compiled and strongly typed delegates. When you call the Update method, you can go through each Action in the list and update the destination from the source.
No reflection and all of the compiling and such is done once, ahead of the Update call.
public class DataMapper<TSourceType, TTargetType> : IDataUpdater<TSourceType, TTargetType>
{
List<Action<TSourceType, TTargetType>> _mappers = new List<Action<TSourceType, TTargetType>>();
DataMapper<TTargetType, TSourceType> _reverseMapper;
public DataMapper() : this(false) { }
public DataMapper(bool isReverse)
{
if (!isReverse)
{
_reverseMapper = new DataMapper<TTargetType, TSourceType>(isReverse: true);
}
}
public DataMapper<TSourceType, TTargetType> Map<TSourceValue, TTargetValue>(
Expression<Func<TSourceType, TSourceValue>> sourcePropExpr,
Expression<Func<TTargetType, TTargetValue>> targetPropExpr)
{
var mapExpression = Expression.Assign(targetPropExpr.Body, sourcePropExpr.Body);
_mappers.Add(
Expression.Lambda<Action<TSourceType, TTargetType>>(
mapExpression,
sourcePropExpr.Parameters[0],
targetPropExpr.Parameters[0])
.Compile());
if (_reverseMapper != null) _reverseMapper.Map(targetPropExpr, sourcePropExpr);
return this;
}
public DataMapper<TSourceType, TTargetType> Map<TSourceValue, TTargetValue>(
Expression<Func<TSourceType, TSourceValue>> sourcePropExpr,
Expression<Func<TTargetType, TTargetValue>> targetPropExpr,
Func<TSourceValue, TTargetValue> sourceToTargetConverter,
Func<TTargetValue, TSourceValue> targetToSourceConverter)
{
var convertedSourceExpression = Expression.Invoke(Expression.Constant(sourceToTargetConverter), sourcePropExpr.Body);
var mapExpression = Expression.Assign(targetPropExpr.Body, convertedSourceExpression);
_mappers.Add(
Expression.Lambda<Action<TSourceType, TTargetType>>(
mapExpression,
sourcePropExpr.Parameters[0],
targetPropExpr.Parameters[0])
.Compile());
if (_reverseMapper != null) _reverseMapper.Map(targetPropExpr, sourcePropExpr, targetToSourceConverter, sourceToTargetConverter);
return this;
}
public void Update(TSourceType source, TTargetType target)
{
foreach (var mapper in _mappers)
{
mapper(source, target);
}
}
public void Update(TTargetType source, TSourceType target)
{
if (_reverseMapper != null)
{
_reverseMapper.Update(source, target);
}
else
{
throw new Exception("Reverse mapper is null. Did you reverse twice?");
};
}
}
The expression is built by taking the expressions that are passed in and using them as parts for the new expression.
Say you called .Map(x => x.PropertyA, y => y.PropertyAA). You now have 2 expressions each with a parameter x and y and each with a body x.PropertyA and y.PropertyAA.
Now you want to re-assemble these expression parts into an assignment expression like y.PropertyAA = x.PropertyA. This is done in the line var mapExpression = Expression.Assign(targetPropExpr.Body, sourcePropExpr.Body); which gives you an expected expression.
Now when you call Expression.Lambda, you are incorporating the parameters (x,y) into a new expression that looks like (x,y) = > y.PropertyAA = x.PropertyA.
Before you can execute this, you need to compile it, hence the .Compile(). But since you only need to compile this once for any given map, you can compile and store the result. The uncompiled expression is of type Expression<Action<TSourceType,TTargetType>> and after it is compiled the resulting type is Action<TSourceType,TTargetType>