I dont know how to get rid of this error ?
Error 1 Using the generic type 'System.Collections.Generic.IEnumerable' requires 1 type arguments C:\Users\huzaifa.gain\documents\visual studio 2010\Projects\VendInvoiceImport\VendInvoiceImport\Program.cs 34 24 VendInvoiceImport
private static IEnumerable<string , string > DistinctInvoiceNumber(DataTable VendorInvoiceStagingTable)
{
var InvoiceLinecollection = VendorInvoiceStagingTable.AsEnumerable().Select(t => new { number = t.Field<string>(VendInvoice.Number),LineNumber = t.Field<string>(VendInvoice.LineNumber)}).Distinct();
return InvoiceLinecollection;
}
Your Linq query returns an sequence of anonymous type, but methods can't return anonymous types. You have several options:
return an IEnumerable<Tuple<string, string>>
private static IEnumerable<Tuple<string, string>> DistinctInvoiceNumber(DataTable VendorInvoiceStagingTable)
{
var InvoiceLinecollection = VendorInvoiceStagingTable
.AsEnumerable()
.Select(t => Tuple.Create(t.Field<string>(VendInvoice.Number), t.Field<string>(VendInvoice.LineNumber)))
.Distinct();
return InvoiceLinecollection;
}
return a IDictionary<string, string> as suggested in another answer (assuming your query doesn't return duplicate keys)
private static IDictionary<string, string> DistinctInvoiceNumber(DataTable VendorInvoiceStagingTable)
{
var InvoiceLinecollection = VendorInvoiceStagingTable
.AsEnumerable()
.Select(t => Tuple.Create(t.Field<string>(VendInvoice.Number), t.Field<string>(VendInvoice.LineNumber)))
.Distinct()
.ToDictionary(t => t.Item1, t => t.Item2);
return InvoiceLinecollection;
}
create a class for this purpose with 2 string properties and return a sequence of that class
private static IEnumerable<InvoiceLine> DistinctInvoiceNumber(DataTable VendorInvoiceStagingTable)
{
var InvoiceLinecollection = VendorInvoiceStagingTable
.AsEnumerable()
.Select(t => new InvoiceLine(t.Field<string>(VendInvoice.Number), t.Field<string>(VendInvoice.LineNumber)))
.Distinct();
return InvoiceLinecollection;
}
Why you do not use Dictionary<string, string> instead?
private static Dictionary<string , string > DistinctInvoiceNumber(DataTable VendorInvoiceStagingTable)
{
var InvoiceLinecollection = VendorInvoiceStagingTable.AsEnumerable().Select(t => new { number = t.Field<string>(VendInvoice.Number),LineNumber =
t.Field<string>(VendInvoice.LineNumber)}).ToDictionary();
return InvoiceLinecollection;
}
Related
I would like to pass an expression that represents a variable to used when instantiating an object.
Instead of:
class MyObject : IMyInterface { ... }
var list = db.MyObjects.Where(x => !x.IsDeleted).ToList();
var anotherList = list.Select(x => new AnotherObject() {
Id = x.Id,
Value = x.Value
});
I would like to make this so that a list of objects of IMyInterface can be transformed into another type of list (AnotherObject as example) using defined expressions as so:
var list = db.MyObjects
.Where(x => !x.IsDeleted)
.ToAnotherObjectList(x => x.Id, x => x.Value);
...
public static List<AnotherObject> ToAnotherObjectList<T>(
this IEnumerable<IMyInterface> list,
Expression id,
Expression value)
{
return list.Select(x => new AnotherObject() { Id = id, Value = value }).ToList();
}
I'm not sure how to accomplish this. I know I can use reflection to create objects and set properties by a string but I'm not sure how to pass expressions.
UPDATE
Well, I thought I'd have to do some reflection but it's simpler than what I was thinking. Here's my solution that works in IRL.
public static IEnumerable<AnotherObject> ToAnotherObject<T>(this IEnumerable<T> list, Func<T, int> getId, Func<T, string> getValue, Func<T, bool> getSelected = null) where T : IMyInterface
{
return list.Select(x => new AnotherObject {
Display = getValue(x),
Id = getId(x),
Selected = getSelected != null && getSelected(x),
});
}
You could use a Func<TInput,TReturn> for that. For example:
public static List<AnotherObject> ToAnotherObjectList<T>(
this IEnumerable<T> list,
Func<T, int> getId,
Func<T, object> getValue)
{
return list.Select(x => new AnotherObject() { Id = getId(x), Value = getValue(x) }).ToList();
}
Call:
list.ToAnotherObjectList(i => i.Id, i=> i.Value);
In this example I used Funcs with one parameter (of type T) and return type int/object.
The method MyMethod as a string parameter. Based on the value of this parameter, I'd like get back an expression to use with an OrderBy. I don't find the right syntax for Expression<Func<>> to use with the dictionary (as TValue type)
public void MyMethod(string orderBy)
{
var dico = new Dictionary<string, string>
{
{ "property1", x => x.Name},
{ "property2", x => x.Age},
};
dico.TryGetValue("property1", out string myOrder);
myList.OrderBy(myOrder)......
}
Update :
var dico = new Dictionary<string, Expression<Func<Person, xxxxx>>>
{
{ "property1", x => x.Name},
{ "property2", x => x.Age},
};
Thanks,
I think you may get hints from this:
public void MyMethod(string orderBy)
{
// Assuming Product has 'Name' and 'Age' property ?
var dico = new Dictionary<string, Expression<Func<Product,object>>>
{
{ "property1", x => x.Name},
{ "property2", x => x.Age},
};
Expression<Func<Product,object>> myorder;
dico.TryGetValue(orderBy, out myOrder);
_context.Products.OrderBy(myOrder);
}
If I have a class of classes of static strings, like this:
public class Urls {
public static class App1 {
public static string URL1 = "http://....1";
public static string URL2 = "http://....2";
}
public static class App2 {
public static string URL3 = "http://....3";
public static string URL4 = "http://....4";
}
private static Dictionary<string, string> _dict;
private static Dictionary<string, string> URLDictionary {
get {
if(_dict != null) return _dict;
return _dict = [WHAT GOES HERE?];
}
}
}
I need to use reflection cause I dont want to have to manage a dictionary, I just want to get the fields out of the classes.
What do I put in [WHAT GOES HERE?] in order to made URLDictionary equal to this:
Dictionary<string, string>(){
{"Url1", "http://.....1"},
{"Url2", "http://.....2"},
{"Url3", "http://.....3"},
{"Url4", "http://.....4"}
};
?
Or, even better, this:
Dictionary<string, Dictionary<string, string>>(){
{"App1", new Dictionary<string, string>() {
{"Url1", "http://.....1"},
{"Url2", "http://.....2"},
},
{"App2", new Dictionary<string, string>() {
{"Url3", "http://.....3"},
{"Url4", "http://.....4"},
},
};
There might be a more elegant answer, but this works.
public static Dictionary<string, Dictionary<string, string>> URLs
{
get
{
if (_URLs != null)
return _URLs;
_URLs =
typeof(HealthURLs).GetNestedTypes(BindingFlags.Static | BindingFlags.Public)
.Select(m => new KeyValuePair<string, Dictionary<string, string>>(
m.Name,
m.GetFields()
.Select(k => new KeyValuePair<string, string>(
k.Name,
k.GetValue(null).ToString()))
.ToDictionary(x => x.Key, x => x.Value)))
.ToDictionary(x => x.Key, x => x.Value);
return _URLs;
}
}
_dict = typeof(Urls).GetNestedTypes().ToDictionary(t => t.Name, t => t.GetFields(BindingFlags.Static | BindingFlags.Public).ToDictionary(p => p.Name, p => p.GetValue(null)));
I am trying to make a generic to be used on the Selectors components. It should provide a default pattern result which is based on a type we have made called SelectorViewModel that has an Id, a Description and a Code. Today we have a method that does it using the following query:
var result = Queryable.Where(x => .... )
.OrderBy(x => ... )
.Select(x => SelectorViewModel(x.Id,
x.Name,
x.Code))
.ToList();
It works fine, but we will have a lot of these methods. The question is, how to make the fields defined on the Select method to be possible to pass as parameter to the SelectorViewModel? For sample:
public IEnumerable<SelectorViewModel> Selector<T>(.. idExpression, .. descriptionExpression, .. codeExpression)
{
var result = session.Query<T>
.Where(x => .... )
.OrderBy(x => ... )
.Select(x => SelectorViewModel(idExpression, // id
descriptionExpression, // description
codeExpression /*code*/))
.ToList();
return result;
}
I would like to have something like this on the use of this method:
var result = repository.Selector(x => x.Id, x => x.Name, x => x.Code);
And make these arguments be merged on the expression on the Select method. Is that possible?
Thank you.
you need something like this:
public IEnumerable<SelectorViewModel> Selector<T>(
Func<T, int> idExpression,
Func<T, string> descriptionExpression,
Func<T, string> codeExpression)
{
var result = session.Query<T>
.Where(x => .... )
.OrderBy(x => ... )
.Select(x => new SelectorViewModel(idExpression(x), descriptionExpression(x), codeExpression(x)))
.ToList();
return result;
}
However I prefer something more like a "Factory method", so that you pass a factory that convert T to SelectorViewModel (something like this):
public class SelectorViewModel
{
public static SelectorViewModel GetSelectorViewModel<T>(T input)
{
//create SelectorViewModel how do you prefer
return new SelectorViewModel(input.Id, input.Description, input.Code);
}
public SelectorViewModel(int id, string description, int code)
{
// TODO
}
}
public IEnumerable<SelectorViewModel> Selector<T>(Func<T, SelectorViewModel> factoryMethod)
{
var result = session.Query<T>
.Where(x => .... )
.OrderBy(x => ... )
.Select(x => factoryMethod(x))
.ToList();
return result;
}
this because (personally) I don't like to pass many functions, maybe complex such as:
x => x.property > 2 ? x.name.ToString() : (x.property < 0 ? x.description : x.description + "a")
and, at the end
the code is less readable
no/low support for debugging
long code line (length)
[ps: what I did above can be done with OOP (https://en.wikipedia.org/wiki/Factory_method_pattern)]
From your samples it's not quite clear what query provider are you targeting (EF or NHibernate), so the following is an universal helper method which composes selector expression using prototype expression and small ExpressionVisitor based parameter replacer:
public static class QueryableExtensions
{
public static IQueryable<SelectorViewModel> ToSelectorViewModel<T>(
this IQueryable<T> source,
Expression<Func<T, long>> idSelector,
Expression<Func<T, string>> descriptionSelector,
Expression<Func<T, string>> codeSelector
)
{
Expression<Func<long, string, string, SelectorViewModel>> prototype =
(id, description, code) => new SelectorViewModel { Id = id, Description = description, Code = code };
var parameter = Expression.Parameter(typeof(T), "e");
var body = prototype.Body
.ReplaceParameter(prototype.Parameters[0], idSelector.Body.ReplaceParameter(idSelector.Parameters[0], parameter))
.ReplaceParameter(prototype.Parameters[1], descriptionSelector.Body.ReplaceParameter(descriptionSelector.Parameters[0], parameter))
.ReplaceParameter(prototype.Parameters[2], codeSelector.Body.ReplaceParameter(codeSelector.Parameters[0], parameter));
var selector = Expression.Lambda<Func<T, SelectorViewModel>>(body, parameter);
return source.Select(selector);
}
}
The expression helper used:
public static partial class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
Now assuming your method receives the same idSelector, descriptionSelector and codeSelector arguments as above, the usage would be:
var result = Queryable.Where(x => .... )
.OrderBy(x => ... )
.ToSelectorViewModel(idSelector, descriptionSelector, codeSelector)
.ToList();
I have an IEnumberable> and I want only the list of Keys but cast to the needed type (i.e. perhaps short and not int). This is used in a custom generic multi-select control the binds to but the database needs potientially 'short' to save.
public static IEnumerable<T> GetKeysOnly<T>(this IEnumerable<KeyValuePair<int, string>> values)
{
Dictionary<int, string> valuesDictionary = values.ToDictionary(i => i.Key, i => i.Value);
List<int> keyList = new List<int>(valuesDictionary.Keys);
// Returns 0 records cuz nothing matches
//List<T> results = keyList.OfType<T>().ToList();
// Throws exception cuz unable to cast any items
//List<T> results = keyList.Cast<T>().ToList();
// Doesn't compile - can't convert int to T here: (T)i
//List<T> results = keyList.ConvertAll<T>(delegate(int i) { return (T)i; });
throw new NotImplementedException();
}
public static IEnumerable<short> GetKeysOnly(this IEnumerable<KeyValuePair<int, string>> values)
{
Dictionary<int, string> valuesDictionary = values.ToDictionary(i => i.Key, i => i.Value);
List<int> keyList = new List<int>(valuesDictionary.Keys);
// Works but not flexable and requires extension method for each type
List<short> results = keyList.ConvertAll(i => (short)i);
return results;
}
Any advice how to make my generic extension method work?
Thanks!
You want to get only the keys converted to a short?
var myList = valuesDictionary.Select(x => (short)x.Key).ToList();
// A Dictionary can be enumerated like a List<KeyValuePair<TKey, TValue>>
If you want to go to any type, then you would do something like this:
public static IEnumerable<T> ConvertKeysTo<T>(this IEnumerable<KeyValuePair<int, string>> source)
{
return source.Select(x => (T)Convert.ChangeType(x.Key, typeof(T)));
// Will throw an exception if x.Key cannot be converted to typeof(T)!
}