is it possible to access properties by name, which is a variable? - c#

Sorry if this is asked and answered, I searched but think I don't know the vocabulary to find the answer. Researched reflection but that doesn't seem to be the answer here? I'm a novice obviously. I'm trying/making minor contributions to a mod for the new Battletech game.
I've got this Dictionary and would like to use its keys to set properties as in the foreach below. I don't know if this is at compile or runtime, my guess is compile time...
I put *limb* in as pseudo-code for how I'm imagining it might work. The property mechDef.Head is an object of type LocationLoadoutDef with its property CurrentInternalStructure being float.
Hope that makes sense!
Much obliged for any assistance.
public class Settings {
public readonly Dictionary<string, bool> LimbRepair = new Dictionary<string, bool> {
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
{ "CenterTorso", false },
{ "LeftTorso", false },
{ "RightTorso", false },
{ "LeftLeg", false },
{ "RightLeg", false },
};
}
MechDef mechDef = new MechDef
(__instance.DataManager.MechDefs.Get(id), __instance.GenerateSimGameUID());
foreach (string limb in settings.LimbRepair.Keys) {
if (!settings.LimbRepair[limb]) {
mechDef.*limb*.CurrentInternalStructure = Math.Max
(1f, mechDef.*limb*.CurrentInternalStructure * (float)rng.NextDouble());
}

You can do it with Reflection, but....
This is quite easy to do with Reflection, and you'll probably get a couple answers on here that show you how, but since you are writing a game, I'm guessing you want the best performance possible, and Reflection isn't always going to give you that.
Below is a solution that requires no reflection but still allows you to use the loop structure you want. It just requires a little bit of setup when you create the object, then you can access your properties as if they were in a dictionary.
Solution: Use a dictionary of delegates to map the properties
First we need to write a utility class that represents a property. Since properties can be different types, this is a generic class with a type argument.
class PropertyWrapper<T>
{
private readonly Func<T> _getter;
private readonly Action<T> _setter;
public PropertyWrapper(Func<T> getter, Action<T> setter)
{
_getter = getter;
_setter = setter;
}
public T Value
{
get
{
return _getter();
}
set
{
_setter(value);
}
}
}
The idea behind this class is that you create it to represent any property you want, and call its methods to read and set the property. The class knows how to read and set the property because you tell it how, when you construct it, by passing it a short lambda expression that does the work.
This utility will allow you to put all the properties that represent limbs into a dictionary. Then you can look them up by string, just like your settings. So for example your MechDefinition might look like this:
class MechDef
{
public Limb Head { get; set; }
public Limb LeftArm { get; set; }
public Limb RightArm { get; set; }
public Limb LeftTorso { get; set; }
public Limb RightTorso { get; set; }
public Limb CenterTorso { get; set; }
public Limb RightLeg { get; set; }
public Limb LeftLeg { get; set; }
private readonly Dictionary<string, PropertyWrapper<Limb>> Properties;
public MechDef()
{
Properties = new Dictionary<string, PropertyWrapper<Limb>>
{
{"Head", new PropertyWrapper<Limb>( () => Head, v => Head = v ) },
{"LeftArm", new PropertyWrapper<Limb>( () => LeftArm, v => LeftArm = v ) },
{"RightArm", new PropertyWrapper<Limb>( () => RightArm, v => RightArm = v ) },
{"CenterTorso",new PropertyWrapper<Limb>( () => CenterTorso, v => CenterTorso = v )},
{"RightTorso", new PropertyWrapper<Limb>( () => RightTorso, v => RightTorso = v ) },
{"LeftTorso", new PropertyWrapper<Limb>( () => LeftTorso, v => LeftTorso = v ) },
{"RightLeg", new PropertyWrapper<Limb>( () => RightLeg, v => RightLeg = v ) },
{"LeftLeg", new PropertyWrapper<Limb>( () => LeftLeg, v => LeftLeg = v ) }
};
foreach (var property in Properties.Values) property.Value = new Limb();
}
public Limb this[string name]
{
get
{
return Properties[name].Value;
}
set
{
Properties[name].Value = value;
}
}
}
Yes, there is a bit of setup there, but it's all in one place, and it only executes once, when you instantiate the MechDef. Now you can access all of the limbs by string:
foreach (var pair in settings.LimbRepair)
{
if (pair.Value != false) continue;
var limb = mechDef[pair.Key];
limb.CurrentInternalStructure = Math.Max
(
1.0F,
limb.CurrentInternalStructure * (float)rng.NextDouble()
);
}
Link to DotNetFiddle example

You can create a DynamicObject to create your own dynamic Dictionary, See the explanation here
Assume that you want to provide alternative syntax for accessing
values in a dictionary, so that instead of writing
sampleDictionary["Text"] = "Sample text", you can write
sampleDictionary.Text = "Sample text".
This is the example from the same MSDN article above:
public class DynamicDictionary : DynamicObject
{
// The inner dictionary
Dictionary<string, object> dictionary = new Dictionary<string, object>();
public int Count
{
get { return dictionary.Count; }
}
// If you try to get a value of a property not defined
// in the class, this method is called.
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
// Converting the property name to lowercase so
// that property names become case-insensitive.
string name = binder.Name.ToLower();
// If the property name is found in a dictionary, set the result parameter
// to the property value and return true. Otherwise, return false.
return dictionary.TryGetValue(name, out result);
}
// If you try to set a value of a property that is not
// defined in the class, this method is called.
public override bool TrySetMember(SetMemberBinder binder, object value)
{
// Converting the property name to lowercase so that
// property names become case-insensitive.
dictionary[binder.Name.ToLower()] = value;
// You can always add a value to a dictionary, so this method always returns true.
return true;
}
}
And this is how you can use your DynamicDictionary:
dynamic person = new DynamicDictionary();
// Adding new dynamic properties. The TrySetMember method is called.
person.FirstName = "Ellen";
person.LastName = "Adams";

Reflection is one way to get at it. https://stackoverflow.com/a/1954663/83250 actually answers this perfectly. I would however restructure your data so the mechDef object is another dictionary but if you must keep it like your question asks, this will work:
void Main()
{
Dictionary<string, bool> limbRepair = new Dictionary<string, bool>
{
{ "Head", false },
{ "LeftArm", false },
{ "RightArm", false },
// Etc.
};
MechDefinition mechDef = new MechDefinition();
List<Limb> limbs = new List<Limb>();
foreach (KeyValuePair<string, bool> limbsToRepair in limbRepair.Where(x => !x.Value))
{
Limb limb = mechDef.GetPropValue<Limb>(limbsToRepair.Key);
limb.CurrentInternalStructure = 9001;
}
}
public class MechDefinition
{
public MechDefinition()
{
Head = new Limb
{
Id = Guid.NewGuid(),
DateAdded = DateTime.Parse("2018-01-01"),
Name = "Main Head",
CurrentInternalStructure = 8675309
};
}
public Guid Id { get; set; }
public string Name { get; set; }
public int CurrentInternalStructure { get; set; }
public Limb Head { get; set; } = new Limb();
public Limb LeftArm { get; set; } = new Limb();
public Limb RightArm { get; set; } = new Limb();
// etc...
}
public class Limb
{
public Guid Id { get; set; }
public string Name { get; set; }
public DateTime DateAdded { get; set; }
public int CurrentInternalStructure { get; set; }
public bool IsDisabled { get; set; }
}
public static class ReflectionHelpers
{
public static object GetPropValue(this object obj, string name)
{
foreach (string part in name.Split('.'))
{
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
public static T GetPropValue<T>(this object obj, string name)
{
object retval = GetPropValue(obj, name);
if (retval == null) { return default(T); }
// throws InvalidCastException if types are incompatible
return (T)retval;
}
}
Be aware that reflection is a very costly operation. If you are dealing with large sets of data, it will be very inefficient. Take a look at https://stackoverflow.com/a/7478557/83250 for a performance overview.
Also code-wise, I prefer to stay away from dynamic and reflection altogether. Reflection has its perks when you need to access a property attribute and dynamic is great if you don't have a strongly typed object. With that said, C# is a strongly typed language and should be treated as such whenever possible. By restructuring your mechDef as a Dictionary<string, Limb> object or something similar you will have a more efficient application.

If I understand correctly, You have something like this:
class LocationLoadoutDef
{
public LocationLoadoutDef()
{
Head = new Prop();
LeftArm = new Prop();
RightArm = new Prop();
CenterTorso = new Prop();
LeftTorso = new Prop();
RightTorso = new Prop();
LeftLeg = new Prop();
RightLeg = new Prop();
}
public Prop Head { get; set; }
public Prop LeftArm { get; set; }
public Prop RightArm { get; set; }
public Prop CenterTorso { get; set; }
public Prop LeftTorso { get; set; }
public Prop RightTorso { get; set; }
public Prop LeftLeg { get; set; }
public Prop RightLeg { get; set; }
...
}
class Prop
{
public float CurrentInternalStructure { get; set; }
...
}
So you can use reflection getting the type of the object and the property.
This is an example based on your pseudocode:
// your instance of LocationLoadoutDef
var mechDef = new LocationLoadoutDef();
//For reflection you need obtain the type
Type mechType = mechDef.GetType();
// loop your Dictionary
foreach (string limb in LimbRepair.Keys)
{
// If the property is false in the dictionary and the type has a property with that name
if (!LimbRepair[limb] && mechType.GetProperties().Any(p => p.Name == limb))
{
// Obtain the instance of the property
var property = mechType.GetProperty(limb).GetValue(mechDef) ;
// Get the property type
Type propertyType = property.GetType();
// If the property has a property CurrentInternalStructure
if (propertyType.GetProperties().Any(p => p.Name == "CurrentInternalStructure"))
{
// Obtain the current value for CurrentInternalStructure
var currentValue = propertyType.GetProperty("CurrentInternalStructure").GetValue(property);
// calculate the new value (I don't know what is rng)
var newValue = 1f ; //Math.Max(1f, (float)currentValue * (float)rng.NextDouble());
// set de value in the property
propertyType.GetProperty("CurrentInternalStructure").SetValue(property, newValue);
}
}
}

You can always create classic and working if .. else or switch.
Or create dictionary with function to update correct property
public class Repair
{
public bool Active { get; set; }
public Action<MechDef> Update { get; set; }
}
public class Settings
{
public readonly Dictionary<string, Repair> LimbRepair =
new Dictionary<string, bool> {
{
"Head",
new Repair { Active = false, mechDef => mechDef.Head.CurrentInternalStructure = yourFunctionForHead }
},
{
"LeftArm",
new Repair { Active = false, mechDef => mechDef.LeftArm.CurrentInternalStructure = yourFunctionForLeftArm }
},
// ... and so on
};
}
Then in the loop you will call correct update action, become much cleaner to use settings class with benefits of strong types and compiler help which prevent dynamic runtime errors
var updates = settings.LimbRepair.Where(pair => pair.Value.Active == false)
.Select(pair => pair.Value);
foreach (var repair in updates)
{
repair.Update();
}

Related

Iterator variable doesn't exist in IEnumerable from which it came?

I have a method which looks like
private Component[] AssociateComponentsWithParametersAndValues(
IEnumerable<Component> components,
IEnumerable<ComponentParameter> parameters,
IEnumerable<ComponentParameterValue> values
)
{
var componentsDictionary = new Dictionary<string, Component>();
var parametersDictionary = new Dictionary<string, ComponentParameter>();
var valuesDictionary = new Dictionary<string, ComponentParameterValue>();
foreach (Component c in components)
{
bool componentMatch = components.Any(co => co == c);
bool identifierMatch = components.Any(co => co.Identifier == c.Identifier);
if (!componentsDictionary.ContainsKey(c.Identifier))
componentsDictionary.Add(c.Identifier, c);
}
// Do a bunch of stuff to mutate the components
return components.ToArray();
}
You would think that componentMatch and identifierMatch would both be true each time right? Instead, componentMatch is always false and identifierMatch is always true. Also, the identifier is (nearly, occasionally there's some bad data) always unique, so it's not like it can be finding another component with the same identifier.
So, there must be something weird with the Component class. Well, here's what it looks like
public class Component : ConfigurationObject
{
public string Parent { get; set; }
public string Type { get; set; }
public string Module { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string TypeName { get; set; }
public bool? Enabled { get; set; }
public string DBIdentifier { get; set; }
public Dictionary<string, ComponentParameterAndValues> ParametersAndValues { get; set; }
public override string Identifier => DBIdentifier;
}
And here's the class it implements
public abstract class ConfigurationObject
{
public abstract string Identifier { get; }
}
Why is this happening?
The only way I could see this break, is if IEnumerable<Component> components is a lazily evaluated enumerable, returning new iterator objects every time. This works:
var list = new List<Component>
{
new Component { Identifier = "Foo" },
new Component { Identifier = "Bar" },
new Component { Identifier = "Baz" },
};
foreach (Component c in list)
{
bool componentMatch = list.Any(co => co == c);
Console.WriteLine($"Component {c.Identifier} match: {componentMatch}");
}
Because == checks reference equality (unless Component overrides it, but it doesn't look like it does). However, if it's not a list, but a new result each iteration:
IEnumerable<Component> list = GetList();
foreach (Component c in list)
{
bool componentMatch = list.Any(co => co == c);
Console.WriteLine($"Component {c.Identifier} match: {componentMatch}");
}
private static IEnumerable<Component> GetList()
{
yield return new Component { Identifier = "Foo" };
yield return new Component { Identifier = "Bar" };
yield return new Component { Identifier = "Baz" };
}
Then it prints false, because foreach() and Any() each get a new collection of new objects, so their references don't match.
The solution would be to enumerate once, and store the components once, materialized in a list, and use that:
var localComponents = components.ToList();
foreach (Component c in localComponents)
{
// ...
}

C# Add element to an Object List using variable as List key

Let me explain, I have a model list in which I have a little more than a thousand parameters, so I have to fill the list with some variables, the thing is that I don't want to do this:
list.Add(new Model{
name1= value,
name2= value,
.....
name1000=value
});
I have an array that contains the names of the parameters in the list, so I was wondering if is possible to use that array of the names and in a loop get the variables fill in, something like this:
list.Add(new Model{
//a loop?
array[0]= value
});
Thanks.
You can achieve this using reflection. Code below
public class ModelFactory
{
private IDictionary<string, PropertyInfo> propertiesInfo { get; set; }
public ModelFactory()
{
this.propertiesInfo = typeof(Model)
.GetProperties()
.ToDictionary(p => p.Name, p => p);
}
public Model Create(string[] propertiesToInitialize, dynamic value)
{
var model = new Model();
foreach (var propertyName in propertiesToInitialize)
{
if (this.propertiesInfo.ContainsKey(propertyName))
{
var property = this.propertiesInfo[propertyName];
property.SetValue(model, value);
}
}
return model;
}
}
Model to initialize
public class Model
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public int MyProperty4 { get; set; }
public int MyProperty5 { get; set; }
}
Usage
public void Test()
{
var propertiesToInitialize = new string[] { "MyProperty1", "MyProperty2", "MyProperty4" };
var modelFactory = new ModelFactory();
var list = new List<Model>();
list.Add(modelFactory.Create(propertiesToInitialize, 500));
Console.WriteLine("MyProperty1 " + list[0].MyProperty1); // 500
Console.WriteLine("MyProperty2 " + list[0].MyProperty2); // 500
Console.WriteLine("MyProperty3 " + list[0].MyProperty3); // 0
Console.WriteLine("MyProperty4 " + list[0].MyProperty4); // 500
Console.WriteLine("MyProperty5 " + list[0].MyProperty5); // 0
}
However as already mentioned in comments, please reconsider your model design because model with these many properties is not optimal.

How to correctly use Expression Trees on properties (without reflection)

Objective: process an object and if the object implements an expected type, I want to change a specific property value (this part is working fine), and I also would like to apply the same logic to all property lists (that I explicit point) that are of the same expected type.
I have the following code:
public abstract class BaseObject
{
public int Id { get; set; }
}
public class Father : BaseObject
{
public DateTime CreatedOn { get; set; }
public string Name { get; set; }
public IEnumerable<ChildA> Children1 { get; set; }
public IEnumerable<ChildB> Children2 { get; set; }
public IEnumerable<ChildA> Children3 { get; set; }
public IEnumerable<ChildB> Children4 { get; set; }
}
public class ChildA : BaseObject
{
public int Val1 { get; set; }
}
public class ChildB : BaseObject
{
public string Name { get; set; }
public int Total { get; set; }
}
I want to process an object by applying some changes on a specific property on the target object and on all property children that I explicit say:
public void Start()
{
var listA = new List<ChildA> { new ChildA { Id = 1, Val1 = 1 }, new ChildA { Id = 2, Val1 = 2 } };
var listB = new List<ChildB> { new ChildB { Id = 1, Name = "1", Total = 1 } };
var obj = new Father { Id = 1, CreatedOn = DateTime.Now, Name = "F1", ChildrenA = listA, ChildrenB = listB };
// I explicit tell to process only 2 of the 4 lists....
ProcessObj(obj, x => new object[] { x.Children1, x.Children2 });
}
I was able to write this function:
public void ProcessObj<T>(T obj, Expression<Func<T, object[]>> includes = null)
{
var objBaseObject = obj as BaseObject;
if (objBaseObject == null) return;
// Here I change the ID - add 100 just as an example....
objBaseObject.Id = objBaseObject.Id + 100;
if (includes == null) return;
var array = includes.Body as NewArrayExpression;
if (array == null) return;
var exps = ((IEnumerable<object>)array.Expressions).ToArray();
for (var i = 0; i < exps.Count(); i++)
{
var name = ((MemberExpression)exps[i]).Member.Name;
var childProperty = obj.GetType().GetProperties(
BindingFlags.Public | BindingFlags.Instance
).FirstOrDefault(prop => prop.Name == name);
if (childProperty == null) continue;
// NOT correct because I think I am getting a copy of the object
// and not pointing to the object in memory (by reference)
var childList = childProperty.GetValue(obj);
// TODO: loop on the list and apply the same logic as the father....
// change the ID field....
}
}
In this prototype I started writing reflection, but I really would like to avoid it if possible....
How can I do this???
Maybe I'm missing something, but it seems like you're complicating the problem by using expression trees. Can you just not use a regular Action and Func delegates to do this? Why do they need to be expression trees? Here's an example just using delegates:
public void ProcessObj<T>(T obj, Func<T, IEnumerable<object>> includes) {
var objBaseObject = obj as BaseObject;
if (objBaseObject == null) return;
// Create a reusable action to use on both the parent and the children
Action<BaseObject> action = x => x.Id += 100;
// Run the action against the root object
action(objBaseObject);
// Get the includes by just invoking the delegate. No need for trees.
var includes = includes(obj);
// Loop over each item in each collection. If the types then invoke the same action that we used on the root.
foreach(IEnumerable<object> include in includes)
{
foreach(object item in include)
{
var childBaseObject = item as BaseObject;
if(childBaseObject != null)
{
action(childBaseObject);
}
}
}
}
Useable just like before:
ProcessObj(obj, x => new object[] { x.Children1, x.Children2 });
No expression trees and no reflection, just regular delegate lambdas.
Hope that helps

CRUD over two different collections of POCOs

I have an interesting question, one I'm having difficulty searching for an answer on.
I have two IEnumerable collections of objects. The underlying objects are completely separate, BUT I can identify a shared key that should match. The collections are important, in that my "left" object is the "system of record", and the "right" object is representing a system I need to ensure matches the system of record.
Once they are matched, I need to perform CRUD operations on one side to bring the right side in line with the left side. For example, it would create a new item on the right side if one didn't exist, or update values, or delete if the item was missing on the left, but not the right.
The catch is, I have hundreds of these collections to match up, and the actual CRUD code is different.
I'd like to introduce some shared code where I can pass in both collections, the collection types (as probably generics), some kind of comparer, and some delegates of what operation to perform for CRUD.
If this code actually existed, it may look something like this
class Stuff
{
string Id {get; set;}
string Name {get; set;}
}
class Junk
{
string Id {get; set;}
string ShortName {get; set;}
}
IEnumerable<Stuff> myStuff = GetStuff();
IEnumerable<Junk> myJunk = GetJunk();
CrudComparer cc = new CrudComparer<Stuff, Junk>(myStuff, myJunk);
cc.Comparer = (leftObject, rightObject) => {
leftObject.Name == rightObject.Name
}
cc.CreateOperation = (newObject, rightCollection) => {
Junk j = new Junk();
j.Shortname = newObject.Name;
rightCollection.Add(j);
}
cc.UpdateOperation = (leftObject, rightObject) => {
rightObject.Shortname = leftObject.Name;
}
cc.DeleteOperation = (rightCollection, rightObject) => {
rightCollection.Remove(rightObject);
}
cc.Compare();
Has anyone ever seen code that does something like this? I'd hate to reinvent the wheel if I can grab something already done.
Thanks for any help!
--Michael
I got to thinking more about this, and realized what I knew about delgates and generics should be sufficient to solve this problem, so I got in LinqPad and had some fun. I haven't written any unit tests around this yet, so use at your own risk, but hopefully if you want to use this you understand the underlying concepts.
class Blah
{
public int ID { get; set; }
public string BlahName { get; set;}
}
class Bleh
{
public int ID { get; set; }
public string BlehName { get; set;}
}
class CrudComparer<TLeft, TRight>
{
private readonly ICollection<TLeft> _leftCollection;
private readonly ICollection<TRight> _rightCollection;
private readonly Comparer _compareOperation;
private readonly CreateOperation _createOperation;
private readonly UpdateOperation _updateOperation;
private readonly DeleteOperation _deleteOperation;
public delegate bool Comparer(TLeft leftItem, TRight rightItem);
public delegate void CreateOperation(TLeft leftItem, ICollection<TRight> rightCollection);
public delegate void UpdateOperation(TLeft leftItem, TRight rightItem);
public delegate void DeleteOperation(TRight rightItem, ICollection<TRight> rightCollection);
public CrudComparer(ICollection<TLeft> leftCollection, ICollection<TRight> rightCollection, Comparer compareOperation, CreateOperation createOperation, UpdateOperation updateOperation, DeleteOperation deleteOperation)
{
_leftCollection = leftCollection;
_rightCollection = rightCollection;
_compareOperation = compareOperation;
_createOperation = createOperation;
_updateOperation = updateOperation;
_deleteOperation = deleteOperation;
}
public void Compare()
{
foreach (TLeft leftItem in _leftCollection)
{
bool foundItem = false;
foreach (TRight rightItem in _rightCollection)
{
if (_compareOperation(leftItem, rightItem))
{
//these equal
foundItem = true;
}
}
if (foundItem == false)
{
_createOperation(leftItem, _rightCollection);
}
}
List<TRight> itemsToDelete = new List<TRight>();
foreach (TRight rightItem in _rightCollection)
{
bool foundItem = false;
foreach (TLeft leftItem in _leftCollection)
{
if (_compareOperation(leftItem, rightItem))
{
foundItem = true;
_updateOperation(leftItem, rightItem);
break;
}
}
if (!foundItem)
{
itemsToDelete.Add(rightItem);
}
}
foreach (TRight itemToDelete in itemsToDelete)
{
_deleteOperation(itemToDelete, _rightCollection);
}
}
}
void Main()
{
List<Blah> blahItems = new List<Blah>();
blahItems.Add(new Blah() { ID = 1, BlahName = "Blah" });
blahItems.Add(new Blah() { ID = 2, BlahName = "ABC" });
blahItems.Add(new Blah() { ID = 34, BlahName = "XYZ" });
blahItems.Add(new Blah() { ID = 6442, BlahName = "123" });
List<Bleh> blehItems = new List<Bleh>();
blehItems.Add(new Bleh() { ID = 2, BlehName = "12345"});
blehItems.Add(new Bleh() { ID = 6, BlehName = "43232"});
blehItems.Add(new Bleh() { ID = 77, BlehName = "BlahBlah"});
blehItems.Add(new Bleh() { ID = 2334, BlehName = "ZYX"});
CrudComparer<Blah, Bleh>.Comparer compareOperation = (leftObject, rightObject) =>
{
return leftObject.ID == rightObject.ID;
};
CrudComparer<Blah, Bleh>.CreateOperation createOperation = (leftObject, rightCollection) =>
{
rightCollection.Add(new Bleh() { ID = leftObject.ID });
};
CrudComparer<Blah, Bleh>.UpdateOperation updateOperation = (leftObject, rightObject) =>
{
rightObject.BlehName = leftObject.BlahName;
};
CrudComparer<Blah, Bleh>.DeleteOperation deleteOperation = (rightObject, rightCollection) =>
{
rightCollection.Remove(rightObject);
};
CrudComparer<Blah, Bleh> cc = new CrudComparer<Blah, Bleh>(blahItems, blehItems, compareOperation, createOperation, updateOperation, deleteOperation);
cc.Compare();
}

How to create a dynamic LINQ select projection function from a string[] of names?

Using C#...
Is there any way to specify property names for a projection function on a LINQ select method, from an array.
public class Album
{
public int Id { get; set; }
public string Name { get; set; }
public short Rate { get; set; }
public string Genre { get; set; }
public short Tracks { get; set; }
}
public class Class1
{
private void Some<T>()
{
// Example of source
var names = new[] { "Id", "Name", "Tracks" };
var query = myDataContext.
GetTable<T>.
AsQueryable().
Select( /* dynamic projection from names array */ );
// something like
// Select(x => new
// {
// x.Id,
// x.Name,
// x.Tracks
// }
GoAndDoSomethingWith(query);
}
}
Could this be done without System.Linq.Dynamic?
You could use reflection and dynamic types to generate an object with only the specified fields/properties.
Below is a simple way of doing this. You can do optimizations, like having a type cache for the reflection. But this should work for simple fields/properties.
public static object DynamicProjection(object input, IEnumerable<string> properties)
{
var type = input.GetType();
dynamic dObject = new ExpandoObject();
var dDict = dObject as IDictionary<string, object>;
foreach (var p in properties)
{
var field = type.GetField(p);
if (field != null)
dDict [p] = field.GetValue(input);
var prop = type.GetProperty(p);
if (prop != null && prop.GetIndexParameters().Length == 0)
dDict[p] = prop.GetValue(input, null);
}
return dObject;
}
Usage:
//...
var names = new[] { "Id", "Name", "Tracks" };
var projection = collection.Select(x => DynamicProjection(x, names));
//...

Categories