Remove cast operations in expression tree - c#

I want to remove any cast expression in an expression tree. We can assume that the cast is redundant.
For example, both these expressions:
IFoo t => ((t as Foo).Bar as IExtraBar).Baz;
IFoo t => ((IExtraBar)(t as Foo).Bar).Baz;
become this:
IFoo t => t.Bar.Baz
How can you accomplish this?
Sample code
The sample below illustrates a pretty simple scenario. However, my coded fails with an exception:
Unhandled Exception: System.ArgumentException: Property 'IBar Bar' is not defined for type 'ExpressionTest.Program+IFoo'
using System;
using System.Linq.Expressions;
namespace ExpressionTest
{
class Program
{
public interface IBar
{
string Baz { get; }
}
public interface IExtraBar : IBar
{
}
public interface IFoo
{
IBar Bar { get; }
}
public class Foo : IFoo
{
public IBar Bar { get; }
}
static void Main(string[] args)
{
Expression<Func<IFoo, string>> expr = t => ((t as Foo).Bar as IExtraBar).Baz;
Expression<Func<IFoo, string>> expr2 = t => ((IExtraBar)(t as Foo).Bar).Baz;
// Wanted: IFoo t => t.Bar.Baz
var visitor = new CastRemoverVisitor();
visitor.Visit(expr);
Console.WriteLine(visitor.Expression.ToString());
}
public class CastRemoverVisitor : ExpressionVisitor
{
public Expression Expression { get; private set; }
public override Expression Visit(Expression node)
{
Expression ??= node;
return base.Visit(node);
}
protected override Expression VisitUnary(UnaryExpression node)
{
Expression = node.Operand;
return Visit(node.Operand);
}
}
}
}
Final solution
The accepted answer pinpoints the use of Expression.MakeMemberAccess and some interface tricks. We can "improve" the code a bit, to use an interfaced PropertyInfo instead of going through the interfaced getter. I ended up with the following:
public class CastRemoverVisitor : ExpressionVisitor
{
protected override Expression VisitUnary(UnaryExpression node)
{
return node.IsCastExpression() ? Visit(node.Operand) : base.VisitUnary(node);
}
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression is UnaryExpression unaryExpression &&
unaryExpression.IsCastExpression())
{
var propertyInfo = node.Member.ToInterfacedProperty();
if (propertyInfo != null)
{
return base.Visit(
Expression.MakeMemberAccess(
unaryExpression.Operand,
propertyInfo
));
}
}
return base.VisitMember(node);
}
}
// And some useful extension methods...
public static class MemberInfoExtensions
{
public static MemberInfo ToInterfacedProperty(this MemberInfo member)
{
var interfaces = member.DeclaringType!.GetInterfaces();
var mi = interfaces.Select(i => i.GetProperty(member.Name))
.FirstOrDefault(p => p != null);
return mi;
}
}
public static class ExpressionExtensions
{
public static bool IsCastExpression(this Expression expression) =>
expression.NodeType == ExpressionType.TypeAs ||
expression.NodeType == ExpressionType.Convert;
}
And then we use it like this:
var visitor = new CastRemoverVisitor();
var cleanExpr = visitor.Visit(expr);
Console.WriteLine(cleanExpr.ToString());

First off, nice repro. Thank you.
The problem is that the property access (t as Foo).Bar is calling the getter for Foo.Bar, and not the getter for IFoo.Bar (yes, those are different things with different MethodInfos).
You can see this by overriding VisitMember and see the MethodInfo being passed.
However, an approach like this seems to work. We have to unwrap things at the point of the member access, since we can only proceed if we can find an equivalent member to access on the uncasted type:
public class CastRemoverVisitor : ExpressionVisitor
{
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression is UnaryExpression { NodeType: ExpressionType.TypeAs or ExpressionType.Convert, Operand: var operand } &&
node.Member is PropertyInfo propertyInfo &&
operand.Type.IsInterface)
{
// Is this just inheriting a type from a base interface?
// Get rid of the cast, and just call the property on the uncasted member
if (propertyInfo.DeclaringType == operand.Type)
{
return base.Visit(Expression.MakeMemberAccess(operand, propertyInfo));
}
// Is node.Expression a concrete type, which implements this interface method?
var methodInfo = GetInterfaceMethodInfo(operand.Type, node.Expression.Type, propertyInfo.GetMethod);
if (methodInfo != null)
{
return base.Visit(Expression.Call(operand, methodInfo));
}
}
return base.VisitMember(node);
}
private static MethodInfo GetInterfaceMethodInfo(Type interfaceType, Type implementationType, MethodInfo implementationMethodInfo)
{
if (!implementationType.IsClass)
return null;
var map = implementationType.GetInterfaceMap(interfaceType);
for (int i = 0; i < map.InterfaceMethods.Length; i++)
{
if (map.TargetMethods[i] == implementationMethodInfo)
{
return map.InterfaceMethods[i];
}
}
return null;
}
}
I'm sure there cases which will break this (fields come to mind, and I know GetInterfaceMap doesn't play well with generics in some situations), but it's a starting point.

Related

ExpressionVisitor doesn't have it's VisitMethodCall invoked

I am following an example series on MSDN for creating a LINQ Provider and have hit a wall.
I am expecting that when I write the following test that the ExpressionVisitor sub-class in the source-code below has it's VisitMethodCall invoked.
[Fact]
public void DatabaseModeler_provides_table_modeler()
{
var q = new LightmapQuery<AspNetRoles>(new SqliteProvider2());
q.Where(role => role.Name == "Admin");
var result = q.ToList();
}
What happens instead is that the VisitConstant method is invoked. I assume this is because when the Provider is instanced, it assigns it's Expression property a ConstantExpression. I'm not sure if I am doing something wrong or if the guide on MSDN has issues with it preventing me from getting the expression containing the Where method invocation.
This is the source code I have for the IQueryable<T> and IQueryProvider implementations.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
namespace Lightmap.Querying
{
internal class SqliteQueryTranslator : ExpressionVisitor
{
internal StringBuilder queryBuilder;
internal string Translate(Expression expression)
{
this.queryBuilder = new StringBuilder();
this.Visit(expression);
return this.queryBuilder.ToString();
}
public override Expression Visit(Expression node)
{
return base.Visit(node);
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
if (node.Method.DeclaringType != typeof(IQueryable) && node.Method.Name != nameof(Enumerable.Where))
{
throw new NotSupportedException($"The {node.Method.Name} method is not supported.");
}
this.queryBuilder.Append($"SELECT * FROM {node.Method.DeclaringType.Name}");
return node;
}
protected override Expression VisitConstant(ConstantExpression node)
{
return node;
}
private static Expression StripQuotes(Expression expression)
{
while (expression.NodeType == ExpressionType.Quote)
{
expression = ((UnaryExpression)expression).Operand;
}
return expression;
}
}
public abstract class LightmapProvider : IQueryProvider
{
public IQueryable CreateQuery(Expression expression)
{
Type genericParameter = expression.GetType().GetGenericArguments().First();
return (IQueryable)Activator.CreateInstance(typeof(LightmapQuery<>)
.MakeGenericType(genericParameter), new object[] { this, expression });
}
public IQueryable<TElement> CreateQuery<TElement>(Expression expression) => new LightmapQuery<TElement>(this, expression);
object IQueryProvider.Execute(Expression expression)
{
return this.Execute(expression);
}
public TResult Execute<TResult>(Expression expression)
{
return (TResult)this.Execute(expression);
}
public abstract string GetQueryText(Expression expression);
public abstract object Execute(Expression expression);
}
public class SqliteProvider2 : LightmapProvider
{
public override object Execute(Expression expression)
{
var x = new SqliteQueryTranslator().Translate(expression);
return Activator.CreateInstance(typeof(List<>).MakeGenericType(TypeCache.GetGenericParameter(expression.Type, t => true)));
}
public override string GetQueryText(Expression expression)
{
throw new NotImplementedException();
}
}
public class LightmapQuery<TTable> : IOrderedQueryable<TTable>
{
public LightmapQuery(IQueryProvider provider)
{
this.Provider = provider;
this.Expression = Expression.Constant(this);
}
public LightmapQuery(IQueryProvider provider, Expression expression)
{
if (!typeof(IQueryable<TTable>).IsAssignableFrom(expression.Type))
{
throw new Exception();
}
this.Expression = expression;
this.Provider = provider;
}
public Type ElementType => typeof(TTable);
public Expression Expression { get; }
public IQueryProvider Provider { get; }
public IEnumerator<TTable> GetEnumerator()
{
return (this.Provider.Execute<IEnumerable<TTable>>(Expression)).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return (Provider.Execute<IEnumerable>(Expression)).GetEnumerator();
}
}
}
Edit
Having updated my unit test to actually store the IQueryable from the .Where, I'm still not seeing my VisitMethodCall invoked.
[Fact]
public void DatabaseModeler_provides_table_modeler()
{
var q = new LightmapQuery<AspNetRoles>(new SqliteProvider2())
.Where(role => role.Name == "Admin");
var result = q.ToList();
}
After some trial and error and a bit of help in IRC, I was able to identify the problem and resolve it. The issue was that my unit test project, which was a .Net Core project, did not have a reference to the System.Linq.Queryable assembly.
In my unit test
[Fact]
public void DatabaseModeler_provides_table_modeler()
{
var q = new LightmapQuery<AspNetRoles>(new SqliteProvider2());
var q2 = q.Where(role => role.Name == "Admin");
var result = q2.ToList();
}
The Type of q2 is "WhereEnumerableIterator'1" which made us realize that it wasn't returning an IQueryable.
After adding the above reference to the project.json, the Type of q2 turned into "LightmapQuery'1" like I was expecting. With this, my VisitMethodCall method gets hit without issue.
The issue is trivial - you forgot to assign the result of applying Where:
q.Where(role => role.Name == "Admin");
use something like this instead
var q = new LightmapQuery<AspNetRoles>(new SqliteProvider2())
.Where(role => role.Name == "Admin");
var result = q.ToList();

Recursively inspecting a LINQ expression

Let's say I have this expression:
e => e.Name.StartsWith(GetArgument())
Where GetArgument() is defined as follows:
public string GetArgument() { return "Lu"; }
I want this expression to be translated to the following string:
"begins_with(Name, Lu)"
I have developed an expression visitor that visits each sub expression in a recursive manner:
public class MyExpressionTranslator : ExpressionVisitor, IExpressionTranslator<string>
{
// ....
//Implementing IExpressionTranslator<string>
public string Translate(Expression expr)
{
//Begin visiting the expression and its sub expressions
base.Visit(expr);
// I need to return the string here
return null;
}
// Overrides method from base class ExpressionVisitor
protected override MethodCallExpression VisitMethodCall(MethodCallExpression expr)
{
//This method is called when a method call sub expression is visited
//For example, I can check if the method being called is "StartsWith"
if(expr.Method.Name == "StartsWith")
{
// I have no idea what to do here
}
//Proceeds to visit this expression's sub expressions
return base.VisitMethodCall(expr);
}
}
I would use this class as follows:
MyExpressionTranslator translator = // new MyExpressionTranslator(...)
Expression<Func<SomeClass, bool>> expr = e => e.Name.StartsWith(GetArgument());
string result = translator.Translate(expr);
// result should be "begins_with(Name, Lu)"
Providing my base class has a virtual visit method for each expression type (be it a constant, an argument, a method call, or any other), how can I build the expected string output?
What are you trying to accomplish? Something like the below might work. It won't be easy to fill out the other methods though.
class Program
{
static void Main(string[] args)
{
Expression<Func<TestObject, bool>> expr = e => e.FirstName.StartsWith(GetArgument());
var visitor = new MyExpressionTranslator();
var translation = visitor.Translate(expr); // = "begins_with(FirstName, Lu)"
}
static string GetArgument()
{
return "Lu";
}
}
class TestObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IExpressionTranslator<T>
{
T Translate(Expression expr);
}
public class MyExpressionTranslator : ExpressionVisitor, IExpressionTranslator<string>
{
private StringBuilder _sb = null;
public string Translate(Expression expr)
{
_sb = new StringBuilder();
base.Visit(expr);
// I need to return the string here
return _sb.ToString();
}
protected override Expression VisitMethodCall(MethodCallExpression expr)
{
if (expr.Method.Name == "StartsWith")
{
var mainArg = expr.Arguments[0];
var lambda = Expression.Lambda<Func<string>>(mainArg);
var arg = lambda.Compile()();
var member = expr.Object as MemberExpression;
if (member != null)
{
_sb.AppendFormat("begins_with({0}, {1})", member.Member.Name, arg);
}
else
{
//Don't know what you want here.
_sb.AppendFormat("begins_with({0}, {1}))", "(obj)", arg);
}
}
return base.VisitMethodCall(expr);
}
}

Ensure that a lambda expression points to an actual property of a class?

Is there any way to ensure that I can only pass in an expression that points to property on the a class?
public class Foo
{
public string Bar { get; set; }
public void DoSomething()
{
HelperClass.HelperFunc(() => Bar);
}
}
public static class HelperClass
{
public static void HelperFunc(Expression<Func<string>> expression)
{
// Ensure that the expression points to a property
// that is a member of the class Foo (or throw exception)
}
}
Also, if need be, I can change the signature to pass the actual class in as well...
Here is extension method, which converts lambda to property. If lambda does not points to property, exception is thrown
public static PropertyInfo ToPropertyInfo(this LambdaExpression expression)
{
MemberExpression body = expression.Body as MemberExpression;
if (body != null)
{
PropertyInfo member = body.Member as PropertyInfo;
if (member != null)
{
return member;
}
}
throw new ArgumentException("Property not found");
}

Partial application of an expression tree

I have an Expression in the following form:
Expression<Func<T, bool>> predicate = t => t.Value == "SomeValue";
Is it possible to create a 'partially applied' version of this expression:
Expression<Func<bool>> predicate = () => t.Value == "SomeValue";
NB This expression is never actually compiled or invoked, it is merely inspected to generate some SQL.
This could be easily achieved by writing a custom ExpressionVisitor and replacing the parameter with a constant expression that you have captured in a closure:
public class Foo
{
public string Value { get; set; }
}
public class ReplaceVisitor<T> : ExpressionVisitor
{
private readonly T _instance;
public ReplaceVisitor(T instance)
{
_instance = instance;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return Expression.Constant(_instance);
}
}
class Program
{
static void Main()
{
Expression<Func<Foo, bool>> predicate = t => t.Value == "SomeValue";
var foo = new Foo { Value = "SomeValue" };
Expression<Func<bool>> result = Convert(predicate, foo);
Console.WriteLine(result.Compile()());
}
static Expression<Func<bool>> Convert<T>(Expression<Func<T, bool>> expression, T instance)
{
return Expression.Lambda<Func<bool>>(
new ReplaceVisitor<T>(instance).Visit(expression.Body)
);
}
}
I think this should work:
Expression predicate2 = Expression.Invoke(predicate, Expression.Constant(new T() { Value = "SomeValue"}));
Expression<Func<bool>> predicate3 = Expression.Lambda<Func<bool>>(predicate2);
Don't know if this is easily parseable to generate SQL however (it works when compiled - I tried).

Linq expressions and extension methods to get property name

I was looking at this post that describes a simple way to do databinding between POCO properties: Data Binding POCO Properties
One of the comments by Bevan included a simple Binder class that can be used to accomplish such data binding. It works great for what I need but I would like to implement some of the suggestions that Bevan made to improve the class, namely:
Checking that source and target are
assigned
Checking that the properties
identified by sourcePropertyName and
targetPropertyName exist
Checking for type compatibility
between the two properties
Also, given that specifying properties by string is error prone, you could use Linq expressions and extension methods instead. Then instead of writing
Binder.Bind( source, "Name", target, "Name")
you could write
source.Bind( Name => target.Name);
I'm pretty sure I can handle the first three (though feel free to include those changes) but I have no clue how to use Linq expressions and extension methods to be able to write code without using property name strings.
Any tips?
Here is the original code as found in the link:
public static class Binder
{
public static void Bind(
INotifyPropertyChanged source,
string sourcePropertyName,
INotifyPropertyChanged target,
string targetPropertyName)
{
var sourceProperty
= source.GetType().GetProperty(sourcePropertyName);
var targetProperty
= target.GetType().GetProperty(targetPropertyName);
source.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
targetProperty.SetValue(target, sourceValue, null);
}
};
target.PropertyChanged +=
(s, a) =>
{
var sourceValue = sourceProperty.GetValue(source, null);
var targetValue = targetProperty.GetValue(target, null);
if (!Object.Equals(sourceValue, targetValue))
{
sourceProperty.SetValue(source, targetValue, null);
}
};
}
}
The following will return a property name as a string from a lambda expression:
public string PropertyName<TProperty>(Expression<Func<TProperty>> property)
{
var lambda = (LambdaExpression)property;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
{
memberExpression = (MemberExpression)lambda.Body;
}
return memberExpression.Member.Name;
}
Usage:
public class MyClass
{
public int World { get; set; }
}
...
var c = new MyClass();
Console.WriteLine("Hello {0}", PropertyName(() => c.World));
UPDATE
public static class Extensions
{
public static void Bind<TSourceProperty, TDestinationProperty>(this INotifyPropertyChanged source, Expression<Func<TSourceProperty, TDestinationProperty>> bindExpression)
{
var expressionDetails = GetExpressionDetails<TSourceProperty, TDestinationProperty>(bindExpression);
var sourcePropertyName = expressionDetails.Item1;
var destinationObject = expressionDetails.Item2;
var destinationPropertyName = expressionDetails.Item3;
// Do binding here
Console.WriteLine("{0} {1}", sourcePropertyName, destinationPropertyName);
}
private static Tuple<string, INotifyPropertyChanged, string> GetExpressionDetails<TSourceProperty, TDestinationProperty>(Expression<Func<TSourceProperty, TDestinationProperty>> bindExpression)
{
var lambda = (LambdaExpression)bindExpression;
ParameterExpression sourceExpression = lambda.Parameters.FirstOrDefault();
MemberExpression destinationExpression = (MemberExpression)lambda.Body;
var memberExpression = destinationExpression.Expression as MemberExpression;
var constantExpression = memberExpression.Expression as ConstantExpression;
var fieldInfo = memberExpression.Member as FieldInfo;
var destinationObject = fieldInfo.GetValue(constantExpression.Value) as INotifyPropertyChanged;
return new Tuple<string, INotifyPropertyChanged, string>(sourceExpression.Name, destinationObject, destinationExpression.Member.Name);
}
}
Usage:
public class TestSource : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Name { get; set; }
}
public class TestDestination : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string Id { get; set; }
}
class Program
{
static void Main(string[] args)
{
var x = new TestSource();
var y = new TestDestination();
x.Bind<string, string>(Name => y.Id);
}
}
This question is very similar to: Retrieving Property name from lambda expression
(Cross-posting answer from https://stackoverflow.com/a/17220748/1037948)
I don't know if you need to bind to "subproperties", but inspecting the lambda.Body for Member.Name will only return the "final" property, not a "fully-qualified" property.
ex) o => o.Thing1.Thing2 would result in Thing2, not Thing1.Thing2.
This is problematic when trying to use this method to simplify EntityFramework DbSet.Include(string) with expression overloads.
So you can "cheat" and parse the Expression.ToString instead. Performance seemed comparable in my tests, so please correct me if this is a bad idea.
The Extension Method
/// <summary>
/// Given an expression, extract the listed property name; similar to reflection but with familiar LINQ+lambdas. Technique #via https://stackoverflow.com/a/16647343/1037948
/// </summary>
/// <remarks>Cheats and uses the tostring output -- Should consult performance differences</remarks>
/// <typeparam name="TModel">the model type to extract property names</typeparam>
/// <typeparam name="TValue">the value type of the expected property</typeparam>
/// <param name="propertySelector">expression that just selects a model property to be turned into a string</param>
/// <param name="delimiter">Expression toString delimiter to split from lambda param</param>
/// <param name="endTrim">Sometimes the Expression toString contains a method call, something like "Convert(x)", so we need to strip the closing part from the end</pa ram >
/// <returns>indicated property name</returns>
public static string GetPropertyName<TModel, TValue>(this Expression<Func<TModel, TValue>> propertySelector, char delimiter = '.', char endTrim = ')') {
var asString = propertySelector.ToString(); // gives you: "o => o.Whatever"
var firstDelim = asString.IndexOf(delimiter); // make sure there is a beginning property indicator; the "." in "o.Whatever" -- this may not be necessary?
return firstDelim < 0
? asString
: asString.Substring(firstDelim+1).TrimEnd(endTrim);
}//-- fn GetPropertyNameExtended
(Checking for the delimiter might even be overkill)
This is likely more than or not exactly what you asked for but I've done something similar to handle mapping of a property between two objects:
public interface IModelViewPropagationItem<M, V>
where M : BaseModel
where V : IView
{
void SyncToView(M model, V view);
void SyncToModel(M model, V view);
}
public class ModelViewPropagationItem<M, V, T> : IModelViewPropagationItem<M, V>
where M : BaseModel
where V : IView
{
private delegate void VoidDelegate();
public Func<M, T> ModelValueGetter { get; private set; }
public Action<M, T> ModelValueSetter { get; private set; }
public Func<V, T> ViewValueGetter { get; private set; }
public Action<V, T> ViewValueSetter { get; private set; }
public ModelViewPropagationItem(Func<M, T> modelValueGetter, Action<V, T> viewValueSetter)
: this(modelValueGetter, null, null, viewValueSetter)
{ }
public ModelViewPropagationItem(Action<M, T> modelValueSetter, Func<V, T> viewValueGetter)
: this(null, modelValueSetter, viewValueGetter, null)
{ }
public ModelViewPropagationItem(Func<M, T> modelValueGetter, Action<M, T> modelValueSetter, Func<V, T> viewValueGetter, Action<V, T> viewValueSetter)
{
this.ModelValueGetter = modelValueGetter;
this.ModelValueSetter = modelValueSetter;
this.ViewValueGetter = viewValueGetter;
this.ViewValueSetter = viewValueSetter;
}
public void SyncToView(M model, V view)
{
if (this.ViewValueSetter == null || this.ModelValueGetter == null)
throw new InvalidOperationException("Syncing to View is not supported for this instance.");
this.ViewValueSetter(view, this.ModelValueGetter(model));
}
public void SyncToModel(M model, V view)
{
if (this.ModelValueSetter == null || this.ViewValueGetter == null)
throw new InvalidOperationException("Syncing to Model is not supported for this instance.");
this.ModelValueSetter(model, this.ViewValueGetter(view));
}
}
This allows you to create an instance of this object and then use "SyncToModel" and "SyncToView" to move values back and forth. The following piece that goes with this allows you to group multiple of these things and move data back and forth with one call:
public class ModelViewPropagationGroup<M, V> : List<IModelViewPropagationItem<M, V>>
where M : BaseModel
where V : IView
{
public ModelViewPropagationGroup(params IModelViewPropagationItem<M, V>[] items)
{
this.AddRange(items);
}
public void SyncAllToView(M model, V view)
{
this.ForEach(o => o.SyncToView(model, view));
}
public void SyncAllToModel(M model, V view)
{
this.ForEach(o => o.SyncToModel(model, view));
}
}
Usage would look something like this:
private static readonly ModelViewPropagationItem<LoginModel, ILoginView, string> UsernamePI = new ModelViewPropagationItem<LoginModel, ILoginView, string>(m => m.Username.Value, (m, x) => m.Username.Value = x, v => v.Username, (v, x) => v.Username = x);
private static readonly ModelViewPropagationItem<LoginModel, ILoginView, string> PasswordPI = new ModelViewPropagationItem<LoginModel, ILoginView, string>(m => m.Password.Value, (m, x) => m.Password.Value = x, v => v.Password, (v, x) => v.Password = x);
private static readonly ModelViewPropagationGroup<LoginModel, ILoginView> GeneralPG = new ModelViewPropagationGroup<LoginModel, ILoginView>(UsernamePI, PasswordPI);
public UserPrincipal Login_Click()
{
GeneralPG.SyncAllToModel(this.Model, this.View);
return this.Model.DoLogin();
}
Hope this helps!
var pr = typeof(CCategory).GetProperties().Select(i => i.Name).ToList(); ;
declaration:
class Foo<T> {
public string Bar<T, TResult>(Expression<Func<T, TResult>> expersion)
{
var lambda = (LambdaExpression)expersion;
MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
{
memberExpression = (MemberExpression)lambda.Body;
}
return memberExpression.Member.Name;
}
}
Usage:
var foo = new Foo<DummyType>();
var propName = foo.Bar(d=>d.DummyProperty)
Console.WriteLine(propName); //write "DummyProperty" string in shell

Categories