I'm playing with PropertyDescriptor and ICustomTypeDescriptor (still) trying to bind a WPF DataGrid to an object, for which the data is stored in a Dictionary.
Since if you pass WPF DataGrid a list of Dictionary objects it will auto generate columns based on the public properties of a dictionary (Comparer, Count, Keys and Values) my Person subclasses Dictionary and implements ICustomTypeDescriptor.
ICustomTypeDescriptor defines a GetProperties method which returns a PropertyDescriptorCollection.
PropertyDescriptor is abstract so you have to subclass it, I figured I'd have a constructor that took Func and an Action parameters that delegate the getting and setting of the values in the dictionary.
I then create a PersonPropertyDescriptor for each Key in the dictionary like this:
foreach (string s in this.Keys)
{
var descriptor = new PersonPropertyDescriptor(
s,
new Func<object>(() => { return this[s]; }),
new Action<object>(o => { this[s] = o; }));
propList.Add(descriptor);
}
The problem is that each property get's its own Func and Action but they all share the outer variable s so although the DataGrid autogenerates columns for "ID","FirstName","LastName", "Age", "Gender" they all get and set against "Gender" which is the final resting value of s in the foreach loop.
How can I ensure that each delegate uses the desired dictionary Key, i.e. the value of s at the time the Func/Action is instantiated?
Much obliged.
Here's the rest of my idea, I'm just experimenting here these are not 'real' classes...
// DataGrid binds to a People instance
public class People : List<Person>
{
public People()
{
this.Add(new Person());
}
}
public class Person : Dictionary<string, object>, ICustomTypeDescriptor
{
private static PropertyDescriptorCollection descriptors;
public Person()
{
this["ID"] = "201203";
this["FirstName"] = "Bud";
this["LastName"] = "Tree";
this["Age"] = 99;
this["Gender"] = "M";
}
//... other ICustomTypeDescriptor members...
public PropertyDescriptorCollection GetProperties()
{
if (descriptors == null)
{
var propList = new List<PropertyDescriptor>();
foreach (string s in this.Keys)
{
var descriptor = new PersonPropertyDescriptor(
s,
new Func<object>(() => { return this[s]; }),
new Action<object>(o => { this[s] = o; }));
propList.Add(descriptor);
}
descriptors = new PropertyDescriptorCollection(propList.ToArray());
}
return descriptors;
}
//... other other ICustomTypeDescriptor members...
}
public class PersonPropertyDescriptor : PropertyDescriptor
{
private Func<object> getFunc;
private Action<object> setAction;
public PersonPropertyDescriptor(string name, Func<object> getFunc, Action<object> setAction)
: base(name, null)
{
this.getFunc = getFunc;
this.setAction = setAction;
}
// other ... PropertyDescriptor members...
public override object GetValue(object component)
{
return getFunc();
}
public override void SetValue(object component, object value)
{
setAction(value);
}
}
Simply:
foreach (string s in this.Keys)
{
string copy = s;
var descriptor = new PersonPropertyDescriptor(
copy,
new Func<object>(() => { return this[copy]; }),
new Action<object>(o => { this[copy] = o; }));
propList.Add(descriptor);
}
With captured variables, it is where it is declared that is important. So by declaring the captured variable inside the loop, you get a different instance of the capture-class per iteration (the loop variable, s, is technically declared outside the loop).
Marc's solution is of course correct, but I thought I'd expand upon WHY below. As most of us know, if you declare a variable in a for or foreach statement, it only lives as long as what's inside, which makes it seem like the variable is the same as a variable declared in the statement-block of such a statement, but that's not right.
To understand it better, take the following for-loop. Then I'll re-state the "equivalent" loop in a while-form.
for(int i = 0; i < list.Length; i++)
{
string val;
list[i] = list[i]++;
val = list[i].ToString();
Console.WriteLine(val);
}
This works out to in while-form like below: (it isn't exactly the same, because continue will act differently, but for scoping rules, it's the same)
{
int i = 0;
while(i < list.Length)
{
{
string val;
list[i] = list[i]++;
val = list[i].ToString();
Console.WriteLine(val);
}
i++;
}
}
When "exploded" out this way, the scope of the variables becomes clearer, and you can see why it always captures the same "s" value in your program, and why Marc's solution shows where to place your variable so that a unique one is captured every time.
create a local copy of s inside your for loop and use that.
for(string s in this.Keys) {
string key = s;
//...
}
For some additional thoughts on this issue see
http://ericlippert.com/2009/11/12/closing-over-the-loop-variable-considered-harmful-part-one/
Related
I'm trying to create AutoPropertyDataAttribute based on CompositeDataAttribute from this example AutoFixture: PropertyData and heterogeneous parameters.
It works with single set of parameters, but fails with more sets of parameters. Here is code:
public static IEnumerable<object[]> NumericSequence
{
get
{
yield return new object[] {1};
//yield return new object[] {2};
}
}
[Theory]
[AutoPropertyData("NumericSequence")]
public void Test(int? p1, int? p2, int? p3)
{
Assert.NotNull(p1);
Assert.NotNull(p2);
}
public class AutoPropertyDataAttribute : CompositeDataAttribute
{
public AutoPropertyDataAttribute(string propertyName)
: base(
new DataAttribute[] {
new PropertyDataAttribute(propertyName),
new AutoDataAttribute()
})
{
}
}
Trying to uncomment the second yield will break test with message:
System.InvalidOperationException: Expected 2 parameters, got 1 parameters
at Ploeh.AutoFixture.Xunit.CompositeDataAttribute.<GetData>d__0.MoveNext()
at Xunit.Extensions.TheoryAttribute.<GetData>d__7.MoveNext()
at Xunit.Extensions.TheoryAttribute.EnumerateTestCommands(IMethodInfo method)
Same happens with ClassDataAttribute
I ran into this issue and decided to implement a custom DataAttribute to solve the problem. I couldn't use either attribute as a base class (reasons below) so I just took the things I needed from the source of each. Thank you OSS :)
Things to note:
I wanted to change the semantics slightly so that I had the option of yielding single objects rather than arrays. Just makes code look neater for single-object parameters. This meant I couldn't use PropertyDataAttribute as a base class
The fixture needs to be created every time a new set of parameters is generated. This meant I couldn't use AutoDataAttribute as a base class
Gist
Or inline source below:
public class AutoPropertyDataAttribute : DataAttribute
{
private readonly string _propertyName;
private readonly Func<IFixture> _createFixture;
public AutoPropertyDataAttribute(string propertyName)
: this(propertyName, () => new Fixture())
{ }
protected AutoPropertyDataAttribute(string propertyName, Func<IFixture> createFixture)
{
_propertyName = propertyName;
_createFixture = createFixture;
}
public Type PropertyHost { get; set; }
private IEnumerable<object[]> GetAllParameterObjects(MethodInfo methodUnderTest)
{
var type = PropertyHost ?? methodUnderTest.DeclaringType;
var property = type.GetProperty(_propertyName, BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy);
if (property == null)
throw new ArgumentException(string.Format("Could not find public static property {0} on {1}", _propertyName, type.FullName));
var obj = property.GetValue(null, null);
if (obj == null)
return null;
var enumerable = obj as IEnumerable<object[]>;
if (enumerable != null)
return enumerable;
var singleEnumerable = obj as IEnumerable<object>;
if (singleEnumerable != null)
return singleEnumerable.Select(x => new[] {x});
throw new ArgumentException(string.Format("Property {0} on {1} did not return IEnumerable<object[]>", _propertyName, type.FullName));
}
private object[] GetObjects(object[] parameterized, ParameterInfo[] parameters, IFixture fixture)
{
var result = new object[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
if (i < parameterized.Length)
result[i] = parameterized[i];
else
result[i] = CustomizeAndCreate(fixture, parameters[i]);
}
return result;
}
private object CustomizeAndCreate(IFixture fixture, ParameterInfo p)
{
var customizations = p.GetCustomAttributes(typeof (CustomizeAttribute), false)
.OfType<CustomizeAttribute>()
.Select(attr => attr.GetCustomization(p));
foreach (var c in customizations)
{
fixture.Customize(c);
}
var context = new SpecimenContext(fixture);
return context.Resolve(p);
}
public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
{
foreach (var values in GetAllParameterObjects(methodUnderTest))
{
yield return GetObjects(values, methodUnderTest.GetParameters(), _createFixture());
}
}
}
What actually happens
The NumericSequence [PropertyData] defines two iterations.
The composition of NumericSequence [PropertyData] with [AutoData] assumes that there is enough data on each iteration.
However, the actual composition is:
1st iteration: [PropertyData], [AutoData]
2nd iteration: [PropertyData], [n/a]
That's why in the 2nd iteration you eventually run out of data.
Composition
The CompositeDataAttribute respects the LSP in a sense that it is programmed against the base of all data theories, the DataAttribute class.
(That is, there is no assumption that all attributes are composed with [AutoData] at the end.)
For that reason, it can't simply jump from the 2nd iteration to the 1st iteration and grab some [AutoData] values – that would break the LSP.
What you could do
Make the actual composition look like:
1st iteration: [PropertyData], [AutoData]
2nd iteration: [PropertyData], [AutoData]
By defining two properties:
public static IEnumerable<object[]> FirstPropertyData { get {
yield return new object[] { 1 }; } }
public static IEnumerable<object[]> OtherPropertyData { get {
yield return new object[] { 9 }; } }
And then, the original test can be written as:
[Theory]
[AutoPropertyData("FirstPropertyData")]
[AutoPropertyData("OtherPropertyData")]
public void Test(int n1, int n2, int n3)
{
}
The test executes twice and n1 is always supplied by [PropertyData] while n2 and n3 are always supplied by [AutoData].
As a workaround you can restructure the AutoPropertyDataAttribute a bit and use the CompositeDataAttribute internally, rather than deriving from it. Derive from the PropertyDataAttribute instead:
public class AutoPropertyDataAttribute : PropertyDataAttribute
{
public AutoPropertyDataAttribute(string propertyName)
: base(propertyName)
{
}
Then override the GetData method to loop over the values returned by the PropertyDataAttribute, and leverage AutoFixture's InlineAutoData(which derives from CompositeDataAttribute) to fill in the rest of the parameters:
public override IEnumerable<object[]> GetData(System.Reflection.MethodInfo methodUnderTest, Type[] parameterTypes)
{
foreach (var values in base.GetData(methodUnderTest, parameterTypes))
{
// The params returned by the base class are the first m params,
// and the rest of the params can be satisfied by AutoFixture using
// its InlineAutoDataAttribute class.
var iada = new InlineAutoDataAttribute(values);
foreach (var parameters in iada.GetData(methodUnderTest, parameterTypes))
yield return parameters;
}
}
The outer loop iterates over the values returned by the PropertyData (each iteration is a row, with some of the cells filled in). The inner loop fills in the remaining cells.
It's not the prettiest thing, but it seems to work. I like Mark's idea to have AutoFixture try to fill in the remaining cells. One less piece of glue code to write :)
Hope this helps,
Jeff.
I have an object model MyObject with various properties. At one point, I have two instances of these MyObject: instance A and instance B. I'd like to copy and replace the properties in instance A with those of instance B if instance B has non-null values.
If I only had 1 class with 3 properties, no problem, I could easily hard code it (which is what I started doing). But I actually have 12 different object models with about 10 properties each.
What's good way to do this?
Update
Use AutoMapper instead if you need to invoke this method a lot. Automapper builds dynamic methods using Reflection.Emit and will be much faster than reflection.'
You could copy the values of the properties using reflection:
public void CopyValues<T>(T target, T source)
{
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(source, null);
if (value != null)
prop.SetValue(target, value, null);
}
}
I've made it generic to ensure type safety. If you want to include private properties you should use an override of Type.GetProperties(), specifying binding flags.
I have tried what's described by Merge Two Objects into an Anonymous Type by Kyle Finley and it is working perfectly.
With the TypeMerger, the merging is as simple as
var obj1 = new {foo = "foo"};
var obj2 = new {bar = "bar"};
var mergedObject = TypeMerger.MergeTypes(obj1 , obj2 );
That's it! You've got the merged object. Apart from that, there is a provision to ignore specific properties too. You can use the same thing for MVC3 as well.
You can do it using reflection, but as someone stated, it'll have a performance penalty.
Since you're working with an expected class design, you can achieve the same goal by using an extension method like so:
public static class MyClassExtensions
{
public static void Merge(this MyClass instanceA, MyClass instanceB)
{
if(instanceA != null && instanceB != null)
{
if(instanceB.Prop1 != null)
{
instanceA.Prop1 = instanceB.Prop1;
}
if(instanceB.PropN != null)
{
instanceA.PropN = instanceB.PropN;
}
}
}
And later, somewhere in your code:
someInstanceOfMyClass.Merge(someOtherInstanceOfMyClass);
At the end of the day you've centralized this operation in an extension method and if you add or remove a property of your class, you only need to modify extension method's implementation and you'll get everything done.
you can use this package:XASoft
use foo.Merger(bar) method
to combine 2 object to a dynamic object
just like this
var objA = new { a = 1, b = 2, c = 3 };
var newObj = objA.Merger(new { a = "Hey", d = 4, e = 5 });
newObj.e = "There";
newObj.f = 6;
Console.WriteLine(JsonConvert.SerializeObject(newObj));
even if object list works fine too!
private class TestClass
{
public int X { get; set; }
public int Y { get; set; }
}
static void Main(string[] args)
{
var list = new List<TestClass> {
new TestClass{ X=1,Y=2},
new TestClass{ X=3,Y=4}
};
Console.WriteLine(JsonConvert.SerializeObject(list.ListMerger(i => new
{ X = "null value", Z = i.X == 1 ? 0 : 1 })));
}
oops,looks like javascript language...
btw,source code click here
I've created a method similar to some answers above, but it returns a new object merged between 2 objects, and will only merge the second objects value if the first objects value is null.
public T MergeObjects<T>(T primary, T secondary)
{
T obj = (T)Activator.CreateInstance(typeof(T));
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(primary, null);
if (value != null)
prop.SetValue(obj, value, null);
else
{
value = prop.GetValue(secondary, null);
if (value != null)
prop.SetValue(obj, value, null);
}
}
return obj;
}
I've written my own class for this purpose: ObjectMerger.
Basically it uses reflections (and may be slow because of that). It also contains more features e.g. parsing objects for cyclic references and merge them too. My ObjectMerger also contains mechanism to handle more complex classes like Delegate or MemberInfo. Those will be copied completely, other objects in the class are recursively merged.
The Syntax is like:
var initialInstance = new MyObjectBase(); // Initialize first object
var properInstance = new MyObjectWithAlgorithms(); // Initialize second object
var result = ObjectMerger.MergeObjects(properInstance, initialInstance); // Merge Objects into type of "properInstance"
I'm sorry to say that it is NOT FOR USE AS IS, because some external libraries are missing in the repository at the moment due to limitations in my company, but they can easily be rewritten. I hope a can add them in future.
This is the same as #Bas Answer but for Merging 2 Object lists
public class Copycontents
{
public static void Work<T>(IList<T> targetList, IList<T> sourceList, Func<T, int> selector)
{
var matchingPrimaryKey = targetList.Select(x => selector(x)).ToList();
foreach (var thismatchingPrimaryKey in matchingPrimaryKey)
{
CopyValues<T>(targetList.Single(x => selector(x) == thismatchingPrimaryKey),
sourceList.Single(x => selector(x) == thismatchingPrimaryKey));
}
}
private static void CopyValues<T>(T target, T source)
{
Type t = typeof(T);
var properties = t.GetProperties().Where(prop => prop.CanRead && prop.CanWrite);
foreach (var prop in properties)
{
var value = prop.GetValue(source, null);
if (value != null)
prop.SetValue(target, value, null);
}
}
}
I'm trying to get the value of a specified index of a property using reflection.
This answer works for standard properties that are of type List<> for example, but in my case, the collection I am trying to work with is of a different format:
public class NumberCollection : List<int>
{
public NumberCollection()
{
nums = new List<int>();
nums.Add(10);
}
public new int this[int i]
{
get { return (int) nums[i]; }
}
private List<int> nums;
}
public class TestClass
{
public NumberCollection Values { get; private set; }
public TestClass()
{
Values = new NumberCollection();
Values.Add(23);
}
}
class Program
{
static void Main(string[] args)
{
TestClass tc = new TestClass();
PropertyInfo pi1 = tc.GetType().GetProperty("Values");
Object collection = pi1.GetValue(tc, null);
// note that there's no checking here that the object really
// is a collection and thus really has the attribute
String indexerName = ((DefaultMemberAttribute)collection.GetType()
.GetCustomAttributes(typeof(DefaultMemberAttribute),
true)[0]).MemberName;
// Code will ERROR on the next line...
PropertyInfo pi2 = collection.GetType().GetProperty(indexerName);
Object value = pi2.GetValue(collection, new Object[] { 0 });
Console.Out.WriteLine("tc.Values[0]: " + value);
Console.In.ReadLine();
}
}
This code gives an AmbiguousMatchException ("Ambiguous match found."). I know my collection class is somewhat contrived, but can anyone help with this?
One option is to use
var prop = Type.GetProperties()
.Where(prop => prop.DeclaringType == collection.GetType())
.First();
Change Collection.GetType() to another type if you want. But basically: loop over the properties instead of using Type.GetProperty.
If you are looking for all of the default members, you can ask for Type.GetDefaultMembers(), then examine the members to find the one that you are looking for.
Alternatively, if you know the data type of the indexer, you can call GetPropertyInfo with the type array specifier.
I have a project in which I have to get all the variables from a struct in a different class and add all their names to a combo box in a form. My primary issue at the moment is iterating through the struct in a way that I can add each variable individually to the combo box. I tried doing this:
msgVars vars = new msgVars();
foreach (object obj in vars)
{
comboBox1.Items.Add(GetName(obj));
}
but as you probably know, you can't iterate through a struct that way. Is there any way I can do this without hardcoding the variables in?
Also, for reference, this is the GetName function:
static string GetName<T>(T item) where T : struct
{
var properties = typeof(T).GetProperties();
if (properties.Length == 1)
{
return properties[0].Name;
}
else
{
return null;
}
}
If you are looking for a way to access properties of a struct (or class) at runtime without predefining in code that set of properties, what you probably need to use is reflection.
Here's an example:
struct MyStruct
{
private readonly int m_Age;
private readonly string m_LastName;
private readonly string m_FirstName;
public int Age { get { return m_Age; } }
public string LastName { get { return m_LastName; } }
public string FirstName { get { return m_FirstName; } }
public MyStruct( int age, string last, string first )
{
m_Age = age;
m_LastName = last;
m_FirstName = first;
}
}
class StructReflection
{
public static void Main(string[] args)
{
var theStruct = new MyStruct( 40, "Smith", "John" );
PrintStructProperties( theStruct );
}
public static void PrintStructProperties( MyStruct s )
{
// NOTE: This code will not handle indexer properties...
var publicProperties = s.GetType().GetProperties();
foreach (var prop in publicProperties)
Console.WriteLine( "{0} = {1}", prop.Name, prop.GetValue( s, null ) );
}
}
You could try using Reflection. How about storing the information in a Hashtable.
public Hashtable GetPropertyInfo(Person person)
{
var properties = new Hashtable();
PropertyInfo[] propInfo = person.GetType().GetProperties();
foreach (PropertyInfo prop in propInfo)
{
properties.Add(prop.Name, prop.GetValue(person, null));
}
return properties;
}
Then you could write the information out via:
var person = new Person()
Person.Name = "Test";
Person.Age = 21;
var PropertyInfo = GetPropertyInfo(person);
foreach (string key in PropertyInfo.Keys)
{
Console.WriteLine("{0} = {1}", key, PropertyInfo[key]);
}
A struct is a single entity, not a collection of variables. This means that you can't 'iterate' over its properties. What you need to do is get a collection of the property names and iterate over it. Your GetName function can't do this because it just returns the name of the first property.
To add the property names to a combo all you have to do is:
var vars = new msgVars();
foreach(var name in GetNames(vars))
comboBox1.Items.Add(name);
In fact, getting the property name is so easy that you could get rid of GetNames completley and just write
foreach (var prop in typeof(msgVars).GetProperties())
comboBox1.Items.Add(prop.Name);
There are various ways you can write GetNames to return a collection of names. You can fill a List with the property names although the simplest is to have it return an iterator like this:
public static IEnumerable<string> GetNames<T>(T obj) where T:struct
{
var properties = typeof (T).GetProperties();
foreach (var propertyInfo in properties)
{
yield return propertyInfo.Name;
}
}
Finally, you don't really need to pass an instance of your struct to the method, as you are enumerating the structs property names, not their values. You can rewrite GetNames like this
public static IEnumerable<string> GetNames<T>() where T:struct
{
var properties = typeof (T).GetProperties();
foreach (var propertyInfo in properties)
{
yield return propertyInfo.Name;
}
}
and load the names like this
foreach(var name in GetNames<msgVars>())
comboBox1.Items.Add(name);
how is it possible to know whether an object implements an indexer?, I need to share a logic for a DataRow and a IDataReader, but they don't share any interface.
I tried also with generics but don't know what restriction should I put on the where clause.
public class Indexer {
// myObject should be a DataRow or a IDataReader
private object myObject;
public object MyObject {
get { return myObject; }
set { myObject = value; }
}
// won't compile, myObject has no indexer
public object this[int index] {
get { return myObject[index]; }
set { myObject[index] = value; }
}
public Indexer(object myObject) {
this.myObject = myObject;
}
}
public class Caller {
void Call() {
DataRow row = null;
IDataReader reader = null;
var ind1 = new Indexer(row);
var ind2 = new Indexer(reader);
var val1 = ind1[0];
var val2 = ind1[0];
}
}
You'd need to declare an interface with an indexer property, use that interface as the constraint, and the type argument class would need to implement that interface in order to satisfy the constraint.
As you don't control the classes you want to use, that wouldn't work.
An alternative is to make the Indexer class take the get/set operations as separate parameters:
public class Indexer {
private Func<int, object> getter;
private Action<int, object> setter;
public object this[int index]
{
get { return getter(index); }
set { setter(index, value); }
}
public Indexer(Func<int, object> g, Action<int, object> s)
{
getter = g;
setter = s;
}
}
public static class IndexerExtensions
{
public static Indexer ToIndexer(this DataRow row)
{
return new Indexer(n => row[n], (n, v) => row[n] = v);
}
public static Indexer ToIndexer(this IDataReader row)
{
return new Indexer(n => row[n], (n, v) => row[n] = v);
}
}
You could then do this:
DataRow row = null;
IDataReader reader = null;
var ind1 = row.ToIndexer();
var ind2 = reader.ToIndexer();
var val1 = ind1[0];
var val2 = ind1[0];
You could make your Indexer an abstract base class, with two subclasses, one for DataRow, and one for IDataReader.
To make it easier to use, 2 factory methods could exist, such as:
var ind1 = Indexer.CreateFromDataRow(row);
var ind2 = Indexer.CreateFromIDataReader(reader);
They could create a specific base class for that type, with it's own logic for handling the indexing.
This avoids the overhead of checking types constantly for every get/set call (at the cost of a single virtual property instead of a standard property).
get {
DataRow row = myObject as DataRow;
if (row != null)
return row[index];
IDataReader reader = myObject as IDataReader;
if (reader != null)
return reader[index];
}
and use the same logic for set{}