I have an interface with ten fields and i often join two Queryables of this interface. Most of the time all of the ten fields have to be equal but sometimes not. Right now i solve this by having a lot of static extensionmethods but they all look kinda the same and with every variant i add i fear i will add an error (Wrong fields etc...).
public static class MyJoins
{
public static IQueryable<T> JoinOnAll<T, TA, TB>(this IQueryable<TA> query, IQueryable<TB> otherQuery)
where TA : IMyInterface where TB : IMyInterface where T : class, IJoinInterface<TA, TB>, new()
{
return query.Join(otherQuery,
a => new { a.F1, a.F2, a.F3, a.F4, a.F5, a.F6, a.F7, a.F8, a.F9, a.F10 },
b => new { b.F1, b.F2, b.F3, b.F4, b.F5, b.F6, b.F7, b.F8, b.F9, b.F10 },
(t, p) => new T { AA = a, BB = b });
}
public static IQueryable<T> JoinOnAllButF2<T, TA, TB>(this IQueryable<TA> query, IQueryable<TB> otherQuery)
where TA : IMyInterface where TB : IMyInterface where T : class, IJoinInterface<TA, TB>, new()
{
return query.Join(otherQuery,
a => new { a.F1, a.F3, a.F4, a.F5, a.F6, a.F7, a.F8, a.F9, a.F10 },
b => new { b.F1, b.F3, b.F4, b.F5, b.F6, b.F7, b.F8, b.F9, b.F10 },
(t, p) => new T { AA = a, BB = b });
}
public static IQueryable<T> JoinOnAllButF4F7<T, TA, TB>(this IQueryable<TA> query, IQueryable<TB> otherQuery)
where TA : IMyInterface where TB : IMyInterface where T : class, IJoinInterface<TA, TB>, new()
{
return query.Join(otherQuery,
a => new { a.F1, a.F2, a.F3, a.F5, a.F6, a.F8, a.F9, a.F10 },
b => new { b.F1, b.F2, b.F3, b.F5, b.F6, b.F8, b.F9, b.F10 },
(t, p) => new T { AA = a, BB = b });
}
//and many more of this
}
I there a way to pass the fields to compare on as a parameter? (I think there is not)
Are there other ways to solve this mass of nearly duplicated code?
----How i would use this-------------------------
I mainly use it in a way where i split querys, join them and then concat them:
IQueryable a = ......
IQueryable b = ......
var firstPart = a.Where(MyExpression).JoinOnAll(b);
var secondPart = a.Where(OtherExpression).JoinOnAllButF2(b);
var thirdPart = a.Where(AnotherExpression).JoinOnAllButF1F2F8(b);
var joinResult = firstPart.Concat(secondpart).Concat(thirdPart);
var joinResultFiltered = joinResult.WHere(AndAnotherExpression);
return joinResultFiltered;
I have many functions like this but the Expressions and joins are always different.
Additional Info because someone in the Commetns asked:
The interfaces are basically just this
public interface IMyInterface{
public string F1 {get;set;}
public string F2 {get;set;}
// up to F10
}
How about something like this:
public static class MyJoins
{
private sealed class ReplacementVisitor : ExpressionVisitor
{
public ReplacementVisitor(LambdaExpression source, Expression toFind, Expression replaceWith)
{
SourceParameters = source.Parameters;
ToFind = toFind;
ReplaceWith = replaceWith;
}
private IReadOnlyCollection<ParameterExpression> SourceParameters { get; }
private Expression ToFind { get; }
private Expression ReplaceWith { get; }
private Expression ReplaceNode(Expression node) => node == ToFind ? ReplaceWith : node;
protected override Expression VisitConstant(ConstantExpression node) => ReplaceNode(node);
protected override Expression VisitBinary(BinaryExpression node)
{
var result = ReplaceNode(node);
if (result == node) result = base.VisitBinary(node);
return result;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (SourceParameters.Contains(node)) return ReplaceNode(node);
return SourceParameters.FirstOrDefault(p => p.Name == node.Name) ?? node;
}
}
private static Expression<Func<T, object>> BuildJoinFields<T>(LambdaExpression fn) where T : IMyInterface
{
var p = Expression.Parameter(typeof(T), "p");
var visitor = new ReplacementVisitor(fn, fn.Parameters[0], p);
var body = visitor.Visit(fn.Body);
return Expression.Lambda<Func<T, object>>(body, p);
}
public static IQueryable<T> JoinOn<T, TA, TB>(
this IQueryable<TA> query,
IQueryable<TB> otherQuery,
Expression<Func<IMyInterface, object>> fieldsToJoinOn)
where TA : IMyInterface
where TB : IMyInterface,
where T : class, IJoinInterface<TA, TB>, new()
{
Expression<Func<TA, object>> aFields = BuildJoinFields<TA>(fieldsToJoinOn);
Expression<Func<TB, object>> bFields = BuildJoinFields<TB>(fieldsToJoinOn);
return query.Join(otherQuery, aFields, bFields, (a, b) => new T { AA = a, BB = b });
}
}
query.JoinOn(otherQuery, x => new { x.F1, x.F2, x.F3, ... })
Although I'm not convinced the compiler will be able to infer the type for type parameter T.
Another solution. It does not care about interfaces, join key is based on outer type. And if property not found inner type, it will throw exception.
public static class QueryableExtensions
{
public interface IJoinInterface<TA, TB>
{
public TA AA { get; set; }
public TB BB { get; set; }
}
class JoinHandler<TA, TB> : IJoinInterface<TA, TB>
{
public TA AA { get; set; }
public TB BB { get; set; }
}
public static IQueryable<IJoinInterface<TA, TB>> JoinOn<TA, TB, TKey>(
this IQueryable<TA> outer,
IQueryable<TB> inner,
Expression<Func<TA, TKey>> joinKey)
{
var innerParam = Expression.Parameter(typeof(TB), "inner");
var innerKey = BuildKey(joinKey, innerParam);
Expression<Func<TA, TB, IJoinInterface<TA, TB>>> resultExpression = (a, b) => new JoinHandler<TA, TB> {AA = a, BB = b};
var queryExpression = Expression.Call(typeof(Queryable), nameof(Queryable.Join),
new[] { typeof(TA), typeof(TB), typeof(TKey), typeof(IJoinInterface<TA, TB>) }, outer.Expression, inner.Expression,
joinKey, innerKey, resultExpression);
return outer.Provider.CreateQuery<IJoinInterface<TA, TB>>(queryExpression);
}
private static LambdaExpression BuildKey(LambdaExpression source, ParameterExpression param)
{
var body = new MemberReplacer(source.Parameters[0], param).Visit(source.Body);
return Expression.Lambda(body, param);
}
class MemberReplacer : ExpressionVisitor
{
public MemberReplacer(ParameterExpression sourceParam, ParameterExpression destParam)
{
SourceParam = sourceParam;
DestParam = destParam;
}
public ParameterExpression SourceParam { get; }
public ParameterExpression DestParam { get; }
protected override Expression VisitMember(MemberExpression node)
{
if (node.Expression == SourceParam)
{
if (DestParam.Type == SourceParam.Type)
return node.Update(DestParam);
var destProp = DestParam.Type.GetProperty(node.Member.Name);
if (destProp == null)
throw new ArgumentException($"Type '{DestParam.Type.Name}' has no property '{node.Member.Name}'.");
return Expression.MakeMemberAccess(DestParam, destProp);
}
return base.VisitMember(node);
}
}
}
Solution is closer to previous answer, but more universal and do not care about specific interfaces realizations.
Ok, here is the problem:
int a = 111;
int b = 222;
Expression<Func<int>> expr = ()=> someClass.SomeWork(a) + b + 1;
As you see, there is 3 different arguments: someClass, a, b. They are all from another scope of execution, but one isn't. How I can get them? I mean, in general, I want only variables of outter scope.
For example, I want to use it like this:
var result = InvokeAndLog(expr);//this will invoke expression and print out everything I need from these arguments.
Ok, folks, I found answer myself. And here it is:
internal class Program
{
public static int Method1()
{
return new Random(0).Next(10000);
}
public class MyClass
{
private int var = 11111;
public int GetSome(int val)
{
return var * val;
}
}
private static void Main()
{
var clas = new MyClass();
int a = 111;
int b = 222;
Expression<Func<int>> expr = () => a * 2 - clas.GetSome(b) + b + 1 - Method1();
var result = InvokeAndLog(expr);
}
private static T InvokeAndLog<T>(Expression<Func<T>> expr)
{
var visitor = new ArgumentsVisitor();
visitor.Visit(expr);
Console.WriteLine("Inputs: {0}", string.Join(", ", visitor.Arguments));
return expr.Compile()();
}
}
The main class here is ExpressionVisitor descendant. I just overrided its member visitor and aggregated all members into single set:
public class ArgumentsVisitor : ExpressionVisitor
{
private readonly HashSet<MemberInfo> _all = new HashSet<MemberInfo>();
public IEnumerable<MemberInfo> Arguments
{
get { return _all; }
}
protected override Expression VisitMember(MemberExpression node)
{
_all.Add(node.Member);
return base.VisitMember(node);
}
}
Then I applyed visitor to expression and printed out all variables! Thanks, microsoft =)
Please see the code:
class X
{
public string x;
}
class Y : X
{
public string y;
}
class A
{
string a;
public virtual X createX<T>()
where T : X, new()
{
return new T() { x = a };
}
}
class B : A
{
string b;
public override X createX<T>()
{
var x = base.createX<T>();
if (x is Y)
((Y)x).y = b; // Yak.
return y;
}
}
...
var c = new B();
var z = c.createX<Y>(); // Yak. I prefer to not needing to know the type Y
I dislike this code, trying to come up with the better way to refactor it. The general idea is quite simple, each class of the hierarchy has factory method to produce an instance of the counterpart class of mirror hierarchy. I get an instance of the root class or derivative class and need to return the instance of counterpart class or its derivative (as root counterpart class). Any ideas or design pattern I can implement instead?
This is what I have ended up with. All yacks removed. But it is a bit verbose.
class X
{
public string x;
}
class Y : X
{
public string y;
}
class A
{
string a;
protected void setX(X x)
{
x.x = a;
}
public virtual X createX()
{
var x = new X();
setX(x);
return x;
}
}
class B : A
{
string b;
protected void setY(Y y)
{
base.setX(y);
y.y = b;
}
public override X createX()
{
var y = new Y();
setY(y);
return y;
}
}
...
var c = new B();
var z = c.createX();
Could this be what you want ?
class BaseProduct
{
public string x;
}
class ChildProduct : BaseProduct
{
public string y;
}
class BaseFactory
{
string a;
public virtual BaseProduct buildProduct(BaseProduct product = null)
{
if (product == null)
product = new BaseProduct();
product.x = a;
return product;
}
}
class ChildFactory : BaseFactory
{
string b;
public override BaseProduct buildProduct(BaseProduct product = null)
{
if (product == null)
product = new ChildProduct();
//else if (!(product is ChildProduct))
// return null or throw exception
((ChildProduct)product).y = b;
return base.buildProduct(product); //build BaseProduct.x
}
}
...
var cFactory = new ChildFactory();
var cProduct = c.buildProduct(); //create a ChildProduct with x=a, y=b
buildProduct determine whether it has been requested to create a new
product of its own, or some derived-factory requesting it to build its
own part only
You should provide some safeguard mechanism of your own, like checking
whether the product is a derived class from ChildProduct in
ChildFactory.buildProduct. That'll avoid user from passing something like:
childFactory.buildProduct(new BaseProduct()); //yak
I want to update a list of objects(mycapsule, has many other members) when a condition (pred) holds for one of its class members(value). Whenever I change something another thing fails, I'm newbie in C# and really confused.
Can somebody fix my code:
In the best condition I only get get this error but I think many things are missing in my code
The type or namespace name `T' could not be found. Are you missing a using directive or an assembly reference?
here is my code
using System;
using System.Collections.Generic ;
namespace test
{
class MainClass
{
public static List< mycapsule<int,double> > sample= new List< mycapsule<int,double>>();
public static void Main (string[] args)
{
sample.Add(new mycapsule<int,double> {id=1 , value= 1.2});
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x==2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id {get ; set; }
public T value { get ; set; }
public int p; // and more
}
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in sample.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
public T JustValue(mycapsule<int,T> i)
{
return i.value;
}
}
}
Look at your update method:
public bool update(Func<T, bool> predicate, T i)
{
foreach (var x in KeyRecord.FindAll(item => predicate(JustValue(item))) )
{
x.value = i ;
}
return true ;
}
What do you expect T to be here? The method is not generic (it's not written as update<T>) and it's not declared in a generic class.
It's possible that you just want:
public bool update<T>(Func<T, bool> predicate, T i)
... but it's hard to say without knowing what KeyRecord.FindAll looks like. Oh, and you've got the same problem with JustValue.
As a side issue, the method names update and pred don't follow .NET naming conventions, and JustValue is a poor method name in terms of descriptiveness. mycapsule also doesn't follow .NET naming conventions. These things really matter in terms of readability.
I'm afraid this won't work due to type safety reasons. I corrected the code as much as possible and got this:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
List<mycapsule<int, double>> list = sample.FindAll(item => predicate(JustValue(item)));
foreach (var x in list)
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
The error is:
predicate(JustValue(item)) => Argument 1: cannot implicitly convert from double to T
This comes from the fact that you are trying to forcefully call a method that you've specified as taking a generic type T (Func<T, bool>) with a value that is known to be double. Although we know that T will be double from the call to update(pred, 12.3);, nothing prevents me from passing in a predicate that takes an incompatible type e.g.:
public static bool pred(string x)
{
return false;
}
and
update(pred, "asdf");
Which is clearly inconsistent. The compiler is simply trying to prevent you from shooting yourself in the foot accidentally.
To solve this, you could explicitly pass the collection to the update method, thus ensuring that the types are consistent:
public static List<mycapsule<int, double>> sample = new List<mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.5, sample);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public class mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
public static bool update<T>(Func<T, bool> predicate, T i, List<mycapsule<int, T>> list)
{
foreach (var x in list.FindAll(item => predicate(JustValue(item))))
{
x.value = i;
}
return true;
}
public static T JustValue<T>(mycapsule<int, T> i)
{
return i.value;
}
Try this, And for generic method the method definition you have used is not correct.
It should be
//MethodName<T,U>(T para1, U para2)
I have change the code to include reflections, this should work.
Please try and give feedback.
using System;
using System.Collections.Generic;
using System.Reflection;
namespace test
{
class MainClass
{
public static List<Mycapsule<int, double>> sample = new List<Mycapsule<int, double>>();
public static void Main(string[] args)
{
sample.Add(new Mycapsule<int, double> { id = 1, value = 1.2 });
update(pred, 12.3);
}
public static bool pred(double x)
{
if (x == 2.5) return true;
return false;
}
public static bool update<T>(Func<T, bool> predicate, T i)
{
var myCollection = sample.FindAll(p => pred(JustValue<double>(p)));
MainClass mainClass = new MainClass();
foreach (var x in myCollection)
{
MethodInfo changeTypeMethod = typeof(MainClass).GetMethod("GetValue");
object value = changeTypeMethod.Invoke(mainClass, new object[] { i, typeof(T) });
PropertyInfo valueProperty = x.GetType().GetProperty("value");
valueProperty.SetValue(x, value);
}
return true;
}
public T GetValue<T>(T i)
{
return (T)Convert.ChangeType(i, typeof(T));
}
public static T JustValue<T>(Mycapsule<int, T> i)
{
return i.value;
}
}
//Outside the MainClass inside the same namespace
public class Mycapsule<KT, T>
{
public KT id { get; set; }
public T value { get; set; }
public int p; // and more
}
}
I have a c++ class that is very simple:
struct Pt_t
{
T x, y;
template <class T2> operator Pt_t<T2>() { Pt_t<T2> pt = {x, y}; return pt; }
};
That allows me to create a pt that has T as any type I want. I can also do Pt_t<s8> = Pt_t<u64>; without a problem. How do I do the same in C#? I tried the below and got an error:
class Pt<T>
{
public T x, y;
//between operator and <T2>, error CS1031: Type expected
public static implicit operator<T2> Pt<T>(Pt<T2> v) {
Pt<T> r = new Pt<T>();
r.x = v.x;
r.y = v.y;
return r;
}
}
No, I don't think that is possible. You may have to add a method, such as To<T>.
The next problem will be "how to get from T2 to T - you can't just assign them. One option might be a conversion delegate:
public Pt<TDestination> To<TDestination>(
Converter<T, TDestination> converter)
{
if (converter == null) throw new ArgumentNullException("converter");
Pt<TDestination> t = new Pt<TDestination>();
t.x = converter(x);
t.y = converter(y);
return t;
}
...
var p = new Pt<int> { x = 1, y = 2 };
var p2 = p.To(t => t.ToString()); // a Pt<string>
You can use Nemerle: ( http://github.com/rsdn/nemerle ) :
using System.Console;
class A[T]
{
public static #:[From](x : A[From]) : A[T]
{
A()
}
}
class Base{}
class Derived{}
def a = A.[Derived]();
def b : A[Base] = a;
WriteLine($"$a $b");
Output:
A`1[Derived] A`1[Base]
Reflector for code:
internal class A<T>
{
public static implicit operator A<T><From>(A<From> x)
{
return new A<T>();
}
}
public class a
{
public static void Main()
{
A<Derived> a = new A<Derived>();
A<Base> a2 = (A<Base>) a;
Console.WriteLine(Convert.ToString(a) + " " + Convert.ToString(a2));
}
}