Iterate over a generic type<T> - c#

I don't know if this can be possible, but I will try to explain myself the best way that I can. Thank you for your help.
I'm trying to fit these entity objects in an integration with a third-party.
My problem is, I have these 3 entity type from the third-party, ObjectType1, ObjectType2, ObjectType3 object classes, all of these have the same base, so, my idea in order to no repeat the code several times was to create a fuction that accepts one generic list and inside of it, try to cast to the object type that I want and used to save the information in my principal entity.
I don't know if this can be possible or what would you recommend me to do, because what I'm trying to do is not to repeat the code several times.
Thank you again.
public static List<ItemsToSave> TestList<T>(List<T> listOfT)
{
var itemsToSave = new List<ItemsToSave>();
foreach (var item in listOfT)
{
object obj = null;
switch (listOfT)
{
case List<ObjectType1>:
obj = item as ObjectType1;
break;
case List<ObjectType2>:
obj = item as ObjectType2;
break;
case List<ObjectType3>:
obj = item as ObjectType2;
break;
}
var itemtosaveEntity = new ItemsToSave()
{
FirstName = obj.FirstName,
MiddleName = obj.MiddleName,
LastName = obj.LastName,
};
itemsToSave.Add(itemtosaveEntity);
}
return itemsToSave;
}

Try this
var listOfT = new List<BaseType>();
List<ItemsToSave> itemsToSave = ConvertList(listOfT);
public static List<ItemsToSave> ConvertList<T>(List<T> listOfT) where T : BaseType
{
return
listOfT
.Select(i => new ItemsToSave()
{
FirstName = i.FirstName,
MiddleName = i.MiddleName,
LastName = i.LastName,
})
.ToList();
}

You can define your generic function like this:
public static List<ItemsToSave> TestList<T>(List<T> listOfT) where t : BaseClass
This is is called a 'Where generic constraint', read more Here
That way the type you have in your function will be BaseClass and you can access all properties defined in that class.

Related

C# how to return 1 row from List<T> object passed as parameter

I need to return one row of List from my function Selectus.
So I pass to the function Selectus object that reflects database table fields and I need to return one row which match the parameter looking_for:
public static List<T> Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.ToList();//here one record should be returned
}
I do not know how to select one row from the list assuming that T parameter is vary. In SelectusT> method I want to pass as T different objects which reflect fields in database table rather than creatinig separate methods for each select. e.g. call Selectus, where object passed is public class ProductCodes { public int ID { get; set; } public string SapIndex { get; set; } public string SapName { get; set; } }. Then I want to call another Selectus<ProductTypes> for another table etc... So I want to write generic/overall method and use it universally for all types of my objects which reflects the fields of few database tables. The SapIndex property is always in the same place of all objects...
Using prop[1] is incredibly fragile. Who says that the property you're currently interested in is always going to be in second place? What if someone adds another property tomorrow? What if not every T that you use have the same property in the second place on its list of properties? It is quite unclear what your actual goal is here and why you've taken the reflection route.
You would be better off using inheritance or interface implementation here. I'm going to use an interface in this answer, but either would work.
For the sake of clarity, let's assume there is a Code field in all your possible lists, and this is the property you're trying to match with.
Define a reusable interface:
public interface ICodeEntity
{
string Code { get; }
}
Apply your interface to all of the classes that you intend to use for your Selectus method.
public class Person : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
public class Document : ICodeEntity
{
public string Code { get; set; }
// And other properties
}
Add a generic type constraint that limits the use of T only to types that implement your interface.
public static List<T> Selectus<T>(string code)
where T : ICodeEntity
You can now write your code in a way that it relies on the type in question having a Code property, and the compiler will help enforce it.
var db = OrmLiteBaza().Open();
var list = db.Select<T>().ToList();
db.Dispose();
return list.Where(item => item.Code == code).ToList();
Usage examples:
List<Person> peopleWithCodeABC = Selectus<Person>("ABC");
List<Person> documentsWithCodeXYZ = Selectus<Document>("XYZ");
// This will fail if Animal does not implement ICodeEntity
var compilerError = Selectus<Animal>("ABC");
I might not understand fully what you want, but instead of string looking_for you could pass in a Func<,> delegate which acts as a selector.
Something like:
public static List<TField> Selectus<T, TField>(Func<T, TField> selector)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Select(selector); // 'using System.Linq;'
return list_selected_record.ToList();
}
Then I believe it could be called like this:
var list_one = Selectus((ProductCodes x) => x.SapIndex);
var list_two = Selectus((ProductTypes x) => x.SapIndex);
var list_three = Selectus((ProductCodes x) => x.SapName);
With this syntax I leave out the <ProductCodes, string> generic arguments to the method since they can be inferred.
Hmm, maybe you want it in the opposite dimension. You could do:
public static List<T> Selectus<T>(Func<T, bool> predicate)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
var list_selected_record = select_all_list.Where(predicate); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus((ProductCodes x) => x.SapIndex == "ABC");
var list_two = Selectus((ProductTypes x) => x.SapIndex == "ABC");
var list_three = Selectus((ProductCodes x) => x.SapName == "DaName");
or:
var list_one = Selectus<ProductCodes>(x => x.SapIndex == "ABC");
var list_two = Selectus<ProductTypes>(x => x.SapIndex == "ABC");
var list_three = Selectus<ProductCodes>(x => x.SapName == "DaName");
But if it is going to always be the "same" property, like always x.SapIndex (but for different types of x), then Flater's answer looks good.
Otherwise, if you insist, your reflection approach should be possible. Use propety's name, not its index! Let me try:
public static List<T> Selectus<T>(string looking_for)
{
var db = OrmLiteBaza().Open();
var select_all_list = db.Select<T>();
db.Dispose();
const string prop_name = "SapIndex";
var prop = typeof(T).GetProperty(prop_name); // can blow up for bad T
var list_selected_record = select_all_list
.Where(x => (string)(prop.GetValue(x)) == looking_for); // 'using System.Linq;'
return list_selected_record.ToList();
}
with:
var list_one = Selectus<ProductCodes>("ABC");
var list_two = Selectus<ProductTypes>("ABC");
you can change code to return just one element
public static T Selectus<T>(string looking_for)
{
//all select data
var db = OrmLiteBaza().Open();//opening database
var select_all_list = db.Select<T>();//getting all data for <T> object works fine
db.Dispose();
//try to select one row - here I have trouble:
var prop = typeof(T).GetProperties();//properties of passed <T> object
var list_selected_record = from records in select_all_list where prop[1].Name == looking_for select records;//tryin to select one record from <T> object as in looking_for variable
return list_selected_record.FirstOrDefault();//here one record should be returned
}

Reflection: how to get values from object as List<object>

Using reflection, I need a function that accepts a list of generic objects and print its values
List<Gender> genders = new List<Gender> {
new Gender {
Id: 1,
Name: "Male"
},
new Gender {
Id: 2,
Name: "Female"
}
}
PrintListValues(genders, "Name"); // prints Male, Female
PrintListValues has to accept a list as object. And the list can contain any type of object. As long as the generic object have the property passed in, it should print the value of each item in list.
public static void PrintValues(object listObject)
{
// code here
}
Unfortunately that's the way the project requirement is.
Been scratching my head over this one and can't figure it out. Reflection is too difficult for me. If anyone can give me hint that would be great!
Try this:
public static void PrintListValues(IEnumerable<object> seq, string propName)
{
foreach (var obj in seq)
{
var type = obj.GetType();
var prop = type.GetProperty(propName);
var value = prop.GetValue(obj);
Console.WriteLine(value);
}
}
Disclaimer: To play with reflection, the above code is fine. For a real world situation, there might be a few things to check as that code assumes the "happy path".
You likely just need
var values = anyList.Select(x => x.SomeProperty);
Console.WriteLine(string.Join(Environemnt.NewLine,values));
However if you really need to include a string property name
public IEnumerable<object> GetValues<T>(IEnumerable<T> source, string name)
{
var prop = typeof(T).GetProperty(name) ?? throw new ArgumentNullException("typeof(T).GetProperty(propName)");
return source.Select(x => prop.GetValue(x));
}
...
foreach (var value in GetValues(someList,"SomeProperty"))
Console.WriteLine(value);
// or
Console.WriteLine(string.Join(Environemnt.NewLine,GetValues(someList,"SomeProperty"));

Matching class by enum

Hi I have an abstract class Item. Classes like Food, Weapon, etc inherit by this class. All informations about this items are stored in the database, work of C# Code is match the exact class and match it by Enum which is also stored in the database column as integer. My problem is this stupid code wherever I have to use methods of Food, Weapon etc classes
if ((ItemType)userItem.ItemType == ItemType.Food)
{
Food food = new Food(userItem);
food.UseItem(sender);
}
else if ((ItemType)userItem.ItemType == ItemType.Weapon)
{
Weapon weapon = new Weapon(userItem);
weapon.UseItem(sender);
}
In the parameter of constructor of Food, Weapon etc. classes is the the object from database to let know object about its fields.
Is some kind of stuff that will help me to match this types without this code? It really annoys me when I'm looking at it.
You can use factory or creational method to create specific type of item:
public Item CreateItem(UserItem userItem)
{
var itemType = (ItemType)userItem.ItemType;
switch(itemType)
{
case ItemType.Food: return new Food(userItem);
case ItemType.Weapon: return new Weapon(userItem);
// etc
default:
throw new NotSupportedException($"Item type {itemType} is not supported");
}
}
Then use this method to create items and use them. E.g. your current code will look like:
var item = CreateItem(userItem);
item.UseItem(sender); // you don't care about specific type of item
Note: EF can use discriminator column to create entities of appropriate type automatically.
Just register building actions one time:
var builder = new ItemBuilder()
.RegisterBuilder(ItemType.Food, () => new Food())
.RegisterBuilder(ItemType.Weapon, () => new Weapon());
and use it later like this:
var item1 = builder.Build(ItemType.Food);
item1.UseItem(sender)
and here a builder code:
public class ItemBuilder
{
public ItemBase Build(ItemType itemType)
{
Func<ItemBase> buildAction;
if (itemBuilders.TryGetValue(itemType, out buildAction))
{
return buildAction();
}
return null;
}
public ItemBuilder RegisterBuilder(ItemType itemType, Func<ItemBase> buildAction)
{
itemBuilders.Add(itemType, buildAction);
return this;
}
private Dictionary<ItemType, Func<ItemBase>> itemBuilders = new Dictionary<ItemType, Func<ItemBase>> ();
}
Another option use a DI container like unity or somth:
UnityContainer.RegisterType<IItemBase, Food>("ItemType.Food");
UnityContainer.RegisterType<IItemBase, Weapon>("ItemType.Weapon");
and resolve
var item1 = UnityContainer.Resolve<IItemBase>(ItemType.Food.ToString());

HowTo use Dynamic linq with an index instead of a property name

I have an ICollection with objects:
private ObservableCollection<ViewItem> items;
The viewItems have no properties. The data will be accessed via an index with
public object this[int index] {
get{ .... }
set {....}
}
I have a geneal class for filtering. The linq with properies will work fine. I use (the important code only):
Queryable = CreateQueryable((IEnumerable<object>)mItemsSource.SourceCollection, ItemType);
mQuery = Queryable.Where(filterString).Cast<object>();
ilteredCollection = mQuery.ToList();
with:
private static IQueryable CreateQueryable(IEnumerable<object> collection, Type itemType)
{
if (itemType == null) return null;
var queryableList = collection.AsQueryable();
return queryableList.Provider.CreateQuery(
Expression.Call(
typeof(Queryable), "Cast",
new Type[] { itemType },
queryableList.Expression));
}
So I can use a filter string like: Id>10 or Name="abc"
where Id and Name are property names.
But I have also Object in another collection which only have access via index. so I have an where string like:
[0]>10 or [1]="abc"
I didn't find any solution. The only hint I could find is to use:
new(it([idx] as Type)
where idx is element index and Type is a type of this element
e.g.
[0]>10 --> new(it[0] as object)>10
But than I get the error:
{"Operator '=' incompatible with operand types 'DynamicClass1' and 'Int32'"}
Useing a string in my filter like:
new(it[0] as object)>"10"
than the error is:
{"Operator '=' incompatible with operand types 'DynamicClass1' and 'string'"}
So - how can I solve this problem. Because this is a general Filterclass I also don't know the type. So in the as statement I can only use object or something like this.
I hope anyone can help me. Perhaps the dynamic keyword of C# 4.0 will help??
BTW a workaround will be to impement a wrapper in each class with indexer, but this will be a lot of stupid work. And that is something a real programmer don't like ;). I am sure there is a solution!
Cheer up !!
First of all -- How to access Current Instance ?
When parsing a lambda expression with a single unnamed parameter, the members of the unnamed parameter are automatically in scope in the expression string, and the current instance given by the unnamed parameter can be referenced in whole using the keyword it. For example,
customers.Where("Country = #0", country);
is equivalent to
customers.Where("it.Country = #0", country);
Above concept has been explained here.
From above explanation, we can now access the indexer property as it[#0] where #0 is value of index to be passed, as explained below.
//Consider below class
public class Product
{
private NameValueCollection collection = new NameValueCollection();
public string Company { get; set; }
public string Distributor { get; set; }
public int ID { get; set; }
...
public string this[string index]
{
get { return collection[index]; }
set { if(!string.IsNullOrEmpty(value)) collection[index]=value; }
}
}
//Main Code
List<Product> list = new List<Product>();
Product product = new Product() { Company = "Nestle", Distributor = "xyz", ID = 1 };
product["Name"] = "Maggi";
list.Add(product);
var filteredList = list.AsQueryable().Where("it[#0]=#1", "Name", "Maggi"); //Accessing the current item by indexer property
foreach (Product productItem in filteredList)
{
Console.WriteLine(productItem.Company);
}
Hope this helps you !! :)
Your usage of new keyword is wrong.
It does not cast object (nor does as).
Keyword new is used to create new object of anonymous class with the specified properties.
Thus new(it[idx] as Type) will create new object with property Type having the value it[idx]. It is equivalent to C#'s: new { Type = this[idx] }.
As I have already pointed out in Dynamic linq: Is there a way to access object data by index?, you need to cast it in the following manner: Int32(it[0]) > 10 for your pseudo-query [0] > 10.

Would .NET benefit from "named anonymous" types?

Consider this:
var me = new { FirstName = "John", LastName = "Smith" };
This is fine as we can then do this:
Console.WriteLine("{0} {1}", me.FirstName, me.LastName);
However we can't do this:
public T GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
because we don't know the type of T.
We could do this:
public object GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
but then we'd have to inspect the properties of the object using reflection in order to access them:
var p = new Prog();
object o = p.GetMe();
Type t = o.GetType();
foreach (var prop in t.GetProperties())
{
Console.WriteLine(prop.Name + ": " + prop.GetValue(o, null));
}
However what about if we could name an anonymous type as we define it? Of course it would no longer be anonymous, however it would be more succinct and maintainable than a normal class definition.
Consider this:
public Person GetMe()
{
return new public class Person { FirstName = "John", LastName = "Smith" };
}
The benefit being it would then be possible to return the result of a complicated Linq query from a method without having to define the class explicitly.
Consider this relatively complex Linq query:
List<int> list = new List<int>();
var query = from number in list
select
new
{
Number = number,
Square = number*number,
Absolute = Math.Abs(number),
Range = Enumerable.Range(0, number)
};
Instead of defining a class like so:
public class MyNumbers
{
public int Number { get; set; }
public int Square { get; set; }
public int Absolute { get; set; }
public IEnumerable<int> Range { get; set; }
}
in order to return the query variable from a method we could instead just do this:
List<int> list = new List<int>();
return from number in list
select new public class MyNumbers
{
Number = number,
Square = number*number,
Absolute = Math.Abs(number),
Range = Enumerable.Range(0, number)
};
Actually, there's a "hack" that you can do to get an anonymous type back from a method. Consider this:
public object MyMethod()
{
var myNewObject = new
{
stringProperty = "Hello, World!",
intProperty = 1337,
boolProperty = false
};
return myNewObject;
}
public T Cast<T>(object obj, T type)
{
return (T)obj;
}
You can now do this:
var obj = MyMethod();
var myNewObj = Cast(obj, new { stringProperty = "", intProperty = 0, boolProperty = false });
The myNewObj will now be an object of the same Type as the anonymous type.
The language feature you need is:
public var GetMe()
{
return new { FirstName = "John", LastName = "Smith" };
}
That is, var would be valid as a method return type, and the compiler would infer the actual type from whatever is returned. You would then have to do this at the call site:
var me = GetMe();
Any two anonymous types with members of the same type would be the same type, so if you wrote other functions returning the same pattern, they would have the same type. For any types A and B where B has a subset of the members of A, then A is assignment-compatible with B (B is like a base class of A). If you wrote:
public var GetMeFrom(var names)
{
return new { FirstName = names["First"], LastName = names["Last"] };
}
The compiler would effectively define this as a generic method with two type parameters, T1 being the type of names and T2 being the type returned by the indexer on T1 that accepts a string. T1 would be constrained so that it must have an indexer that accepts a string. And at the call site you would just pass anything that had an indexer that accepted a string and returned any type you like, and that would determine the type of FirstName and LastName in the type returned by GetMeFrom.
So type inference would figure all this out for you, automatically capturing whatever type constraints are discoverable from the code.
IMHO the root problem is nothing to do with anonymous types, but that declaring a class is too verbose.
Option 1:
If you could declare a class like this:
public class MyClass
{ properties={ int Number, int Square, int Absolute, IEnumerable<int> Range } }
or some other similarly quick way (like the tuple example) then you wouldn't feel the need to do hacky things with anonymous types just to save some code.
When 'compiler as a service' arrives in C#5, hopefully they'll do a good job of integrating it and we'll be able to use metaprogramming to solve these kinds of problems cleanly. Party like it's 1958!
Option 2:
Alternatively, in C#4, you could just pass an anonymous type around as dynamic and avoid all the casting. Of course this opens you up to runtime errors if you rename a variable, etc.
Option 3:
If C# would implement generics in the same way as C++, then you could pass the anonymous type into a method, and so long as it had the right members, it would just compile. You'd get all the benefits of static type safety, and none of the downsides. Every time I have to type where T : ISomething in C# I get annoyed that they didn't do this!
What you are describing (named anonymous types) are basically "tuple types".
I think they would be a nice addition to C#.
If I were designing such a feature for C#, I would expose it using syntax like this:
tuple<int x, int y>
so that you could do:
public tuple<int x, int y> GetStuff()
{
}
I would then change the definition of anonymous types, so that:
new { x = 2, y = 2}
had tuple<int x, int y> as it's type, rather than an anonymous type.
Getting this to work with the current CLR is a little tricky, because once you can name an anonymous type in public signatures you need to be able to unify them across separately compiled assemblies. It can be accomplished by embedding a "module constructor" inside any assembly that uses a tuple type. See this post for an example.
The only downside to that approach is that it doesn't respect the CLR's "lazy" model for type generation. That means that assemblies that use many distinct tuple types might experience slightly slower load types. A better approach would be to add support for tuple types directly to the CLR.
But, apart from changing the CLR, I think the module constructor approach is the best way of doing something like this.
I would love this feature, there have been many times I've wanted this.
A good example is processing XML. You parse them get back an object, but then you need to make a concrete version of the object to send back to a caller. Many times you get XML that changes quite considerably and requires you make many classes to handle it. Wouldn't it be wonderful if you could just build the object using LinqToXml as a var, then just return that?
I think this would be a nice compiler magic for tuples:
Creating a tuple:
(int, string, Person) tuple = (8, "hello", new Person());
equivalent to:
Tuple<int,string,Person> tuple = new Tuple<int,string,Person>(8 ,"hello", new Person());
In a function:
public (int, string, Person) GetTuple(){
return ...
}
Getting values:
int number = tuple[1];
string text = tuple[2];
Person person = tuple[3];
Could you create an Interface with the properties FirstName and LastName and use that?

Categories