If I interpret the question correctly, then using the code from here : using System; using System. Collections; using System.Collections. Generic; using System.IO; using System.
Reflection; using System.Reflection. Emit; public interface ISomeInterface { void SetSomeBool(bool value); } class SomeBase : ISomeInterface { public virtual bool SomeBool { get; set; } void ISomeInterface. SetSomeBool(bool value) { SomeBool = value; } } class SomeDerived : SomeBase { // ... extends SomeBase } static class Program { static void Main() { var item1 = new SomeBase(); var item2 = new SomeDerived(); var items = new List { item1, item2}; ISomeInterface group = GroupGenerator.
Create(items); group. SetSomeBool(true); Console. WriteLine(item1.
SomeBool); // true Console. WriteLine(item2. SomeBool); // true group.
SetSomeBool(false); Console. WriteLine(item1. SomeBool); // false Console.
WriteLine(item2. SomeBool); // false } } Note that it would also work with properties, but the get will have to throw an exception (the set applies to all). For that reason, I prefer the explicit method approach (no get on the interface).
It could also be a set only property, but they are really rare: public interface ISomeInterface { bool SomeBool { set; } } class SomeBase : ISomeInterface { public virtual bool SomeBool { get; set; } } class SomeDerived : SomeBase { // ... extends SomeBase } static class Program { static void Main() { var item1 = new SomeBase(); var item2 = new SomeDerived(); var items = new List { item1, item2}; ISomeInterface group = GroupGenerator. Create(items); group. SomeBool = true; Console.
WriteLine(item1. SomeBool); // true Console. WriteLine(item2.
SomeBool); // true group. SomeBool = false; Console. WriteLine(item1.
SomeBool); // false Console. WriteLine(item2. SomeBool); // false } }.
If I interpret the question correctly, then using the code from here: using System; using System. Collections; using System.Collections. Generic; using System.IO; using System.
Reflection; using System.Reflection. Emit; public interface ISomeInterface { void SetSomeBool(bool value); } class SomeBase : ISomeInterface { public virtual bool SomeBool { get; set; } void ISomeInterface. SetSomeBool(bool value) { SomeBool = value; } } class SomeDerived : SomeBase { // ... extends SomeBase } static class Program { static void Main() { var item1 = new SomeBase(); var item2 = new SomeDerived(); var items = new List { item1, item2}; ISomeInterface group = GroupGenerator.
Create(items); group. SetSomeBool(true); Console. WriteLine(item1.
SomeBool); // true Console. WriteLine(item2. SomeBool); // true group.
SetSomeBool(false); Console. WriteLine(item1. SomeBool); // false Console.
WriteLine(item2. SomeBool); // false } } Note that it would also work with properties, but the get will have to throw an exception (the set applies to all). For that reason, I prefer the explicit method approach (no get on the interface).
It could also be a set-only property, but they are really rare: public interface ISomeInterface { bool SomeBool { set; } } class SomeBase : ISomeInterface { public virtual bool SomeBool { get; set; } } class SomeDerived : SomeBase { // ... extends SomeBase } static class Program { static void Main() { var item1 = new SomeBase(); var item2 = new SomeDerived(); var items = new List { item1, item2}; ISomeInterface group = GroupGenerator. Create(items); group. SomeBool = true; Console.
WriteLine(item1. SomeBool); // true Console. WriteLine(item2.
SomeBool); // true group. SomeBool = false; Console. WriteLine(item1.
SomeBool); // false Console. WriteLine(item2. SomeBool); // false } }.
I was writing up something similar (but less powerful), but then I realised that my idea (like this) still wouldn't address the desire to be able to pass the name of the to-be-set property as a string. Here you still need to explicitly list in ISomeInterface all the properties you might ever want to set. I think there isn't anyway of avoiding reflection / boiler-plate code if this is a hard requirement.
– AakashM Jan 15 '10 at 17:04 My interpretation is that this approach (with string) is just an illustration of the way he has it working now, via reflection. – Marc Gravell? Jan 15 '10 at 17:43 You interpreted correctly.
Pretty cool stuff. Your code directly led me to my answer, and to ultimately realizing it'd be a bad design choice. I learned some good things though and got to fiddle with some experimental code, no regrets.Thanks.
;) – Siege Jan 15 '10 at 23:04 You're most welcome. – Marc Gravell? Jan 15 '10 at 23:12.
That sounds like you're creating a maintenance nightmare for no good reason. Your problem isn't so bad that you have to invent what is basically a new language feature. Among other things, if you've got a set of types that differ only in terms of how they present information, then you can use other mechanisms other than inheritance to break out the common code.
You can pass a delegate to their "render" methods, for instance, or use the Strategy pattern.
The reason I'd used reflection was to avoid that "maintenance nightmare. " If you're referring to the ending bit (redefining all members), that's specifically why I'm avoiding it (and won't implement it). And I'm not really having a problem, per se, I'm just asking if what I'd like to do is possible in a way that wouldn't become a disaster later on, as you said.
:P – Siege Jan 15 '10 at 16:32 1 The maintenance nightmare I'm talking about is your use of a relatively sophisticated feature (Reflection) to solve a relatively simple problem. Whoever comes after will have to understand and maintain your Reflection code. – John Saunders Jan 15 '10 at 16:33 I totally agree.
The problem seems to have nothing to do with managing the data, but in how it is 'rendered' in one way or another. – Michael Bray Jan 15 '10 at 16:37.
Seems like you're taking a strange path here. You have to use reflection if you don't know at compile time what type you're dealing with. However you could use the new dynamic keyword in .
Net 4.0 and get your class to implement IDynamicMetaObjectProvider to defer call site checks till runtime.
This code uses ConcurrentDictionary from . NET 4, but you could write it using Dictionary and either make it not thread-safe or use coarse locking (the lock statement) and sacrifice a bit of performance. Public static class DynamicObjects { private static readonly ConcurrentDictionary>> _setters = new ConcurrentDictionary>>(); public static void SetProperty(object instance, string property, object value) { if (instance == null) throw new ArgumentNullException("instance"); if (property == null) throw new ArgumentNullException("property"); if (property.
Length == 0) throw new ArgumentException("The property name cannot be empty. ", "property"); Type type = instance.GetType(); var settersForType = _setters. GetOrAdd(type, CreateDictionaryForType); var setter = settersForType.
GetOrAdd(property, (obj, newValue) => CreateSetterForProperty(type, property)); setter(instance, value); } private static ConcurrentDictionary> CreateDictionaryForType(Type type) { return new ConcurrentDictionary>(); } private static Action CreateSetterForProperty(Type type, string property) { var propertyInfo = type. GetProperty(property); if (propertyInfo == null) return (o, v) => ThrowInvalidPropertyException(type, property); var setterMethod = propertyInfo.GetSetMethod(); if (setterMethod == null) return (o, v) => ThrowReadOnlyPropertyException(type, property); ParameterExpression instance = Expression. Parameter(typeof(object), "instance"); ParameterExpression value = Expression.
Parameter(typeof(object), "value"); Expression expression = Expression. Lambda( Expression. Call(instance, setterMethod, Expression.
Convert(value, propertyInfo. PropertyType)), instance, value); return expression.Compile(); } private static void ThrowInvalidPropertyException(Type type, string propertyName) { throw new InvalidOperationException("The type '" + type. FullName + "' does not have a publicly accessible property '" + propertyName + "'."); } private static void ThrowReadOnlyPropertyException(Type type, string propertyName) { throw new InvalidOperationException("The type '" + type.
FullName + "' does not have a publicly visible setter for the '" + propertyName + "' property. "); } }.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.