| PropertyAccessor fails when trying to dynamically read a property that overrides a virtual holding in a base grade. Error message: "Operation could destablize the runtime". Please advise. | | | | If I wanted to use this to access many different classes (all of which use reflection), should I create a carve up form or somehow add this to the base course? What I am trying to ask is best possible strategy Socket Rocket | | | | Hi, Accept a look on my code. Its use generics to convert parameters and return values. Is limited to classes, structs will not work, interfaces should be work but is not implemented. Is for read only simply tin be implemented to write likewise. I believe that is faster because we don't need emit assemblies. What you call up about? using System; using System.Collections.Generic; using System.Linq; using Arrangement.Text; using System.Reflection; namespace ConsoleApplication8 { grade Program { static void Main(string[] args) { var examination = new { asValue = 17, asRef = "test" }; var reader = PropertyToDelegate.CreateDelegate(examination, test.GetType().GetProperty("asValue").GetGetMethod()); Console.WriteLine(reader(test)); reader = PropertyToDelegate.CreateDelegate(test, test.GetType().GetProperty("asRef").GetGetMethod()); Console.WriteLine(reader(test)); // or var blazon = test.GetType(); reader = PropertyToDelegate.CreateDelegate(type, type.GetProperty("asValue").GetGetMethod()); Console.WriteLine(reader(exam)); reader = PropertyToDelegate.CreateDelegate(blazon, blazon.GetProperty("asRef").GetGetMethod()); Console.WriteLine(reader(test)); Console.ReadLine(); } } struct structTest { public int AsValue { go; set; } public string AsRef { get; prepare; } } public consul object Reader(object This); static grade PropertyToDelegate { public static Reader CreateDelegate<T>(T obj, MethodInfo method) where T : course { return PropertyToDelegate<T>.CreateDelegate(method); } public static Reader CreateDelegate(Type type, MethodInfo method) { return (Reader) typeof(PropertyToDelegate<>).MakeGenericType(type).GetMethod("CreateDelegate").Invoke(null, new object[] { method }); } } public static class PropertyToDelegate<T> where T : course { public delegate object TReader(T This); static class BoxerForStructs<South> where S : struct { delegate S structReader(T obj); public static TReader CreateDelegate(MethodInfo method) { var del = (structReader)Delegate.CreateDelegate(typeof(structReader), method); return (T obj) => del(obj); } } public static Reader CreateDelegate(MethodInfo method) { TReader del; if (!method.ReturnType.IsValueType) del = (TReader)Delegate.CreateDelegate(typeof(TReader), method); else del = (TReader)typeof(BoxerForStructs<>).MakeGenericType(typeof(T), method.ReturnType).GetMethod("CreateDelegate").Invoke(null, new object[] { method }); return (This) => del((T)This); } } } | | | | Hi James, I know this is an old thread, merely I thought I'll simply make an ascertainment for those who care to read reviews: i. In SampleApp.cs, if I replace the Blazon.InvokeMember() calls with PropertyInfo.SetValue() and PropertyInfo.GetValue(), those durations are sliced to about 20% - 40% of the original time, provided you lot set the PropertyInfo one time Earlier the loop begins. I suppose information technology is because information technology doesn't have to lookup the property info 1,000,000 times every bit done in Type.InvokeMember() in the test app. What this means is that the REFLECTION part of the examination, which is the slowest, is not optimal. ii. If like me, yous examination the code provided by Tobi (Mr T#), and the generic implementation seems slower, it is only considering he used 100,000,000 test cycles instead of 1,000,000 as used by James. BTW, smashing article, and great code. Very useful. Thanks. Regards, Martin | | | | Hi Every bit I understand from this code is that, this code calls the properties which are bachelor in the class, I can't create a holding. Correct me if i'yard wrong. And what if I desire to create properties dynamically. | | | | First of all, thanks a lot for this slice of work - It is very helpful in what I am trying to do - Pretty much exactly what i was looking for for a long time! I also extended information technology with a PropertyAccessorMgr class which auto-manages all property accessors that take been created and only creates a new 1 if information technology does not already be. Now is in that location an easy way to easily invoke methods or ctors dynamically? I'm not sure if this is the right place to ask but I couldn't seem to find whatsoever more info on this matter - And I figured if dynamic property invocation is working, why not methods or ctors? I'm confident someone hither must have the answer Edit: I realized 2 things that should be mentioned: ane. The containing class must be public (or -I assume- somehow accessible to the PropertyAccessor). 2. You MUST refer to the bodily form of the object whose holding yous desire to evaluate. You cannot use the PropertyAccessor of an underlying type or interface. modified on Tuesday, Baronial v, 2008 v:08 PM | | | | Quick variation based on lambda functions. >---------------------------------------- grade LambdaPropertyAccessor<T> { private Dictionary<string, Func<T, object>> propAccessors = new Dictionary<string, Func<T, object>>(); public LambdaPropertyAccessor() { Type type = typeof (T); foreach (PropertyInfo pi in type.GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance)) { if (!pi.CanRead) continue; ParameterExpression parameter = Expression.Parameter(type, "r"); Expression<Func<T, object>> lambda; if (pi.PropertyType.IsValueType) { lambda = Expression.Lambda<Func<T, object>>( Expression.TypeAs(Expression.Property(parameter, pi.Name), typeof(object)), parameter); } else { lambda = Expression.Lambda<Func<T, object>>(Expression.Property(parameter, pi.Name), parameter); } propAccessors.Add(pi.Name, lambda.Compile()); } } public object Become(T obj, cord propName) { return propAccessors[propName](obj); } } <---------------------------------------- 1000000 property gets on integer... Direct access ms: 15,625 PropertyAccessor (Reflection.Emit) ms: 78,125 Reflection ms: 4687,5 Lambda ms: 218,75 meg belongings gets on strings... Direct access ms: xv,625 PropertyAccessor (Reflection.Emit) ms: 46,875 Reflection ms: 4765,625 Lambda ms: 203,125 | | | | This is pretty absurd. How would you get most implementing a holding setter with a lamda? | | | | Belongings setter implementation will be a "statement lambda". I'm not sure that it can be implemented using System.Linq.Expressions. | | | | Y'all can create dynamic setters. Add the following lawmaking to the loop in the constructor: <br /> ParameterExpression paramExpT = Expression.Parameter(typeof(T), " instance");<br /> ParameterExpression paramExpObj = Expression.Parameter(typeof(object), " obj");<br /> Action<T, object> setterLambda =<br /> Expression.Lambda<Activeness<T, object>>(<br /> Expression.Call(paramExpT, pi.GetSetMethod(),<br /> Expression.ConvertChecked(paramExpObj, pi.PropertyType)), paramExpT, paramExpObj)<br /> .Compile();<br /> propSetters.Add(pi.Name, setterLambda);<br /> where propSetters is a member variable: <br /> private Dictionary<cord, Action<T, object>> propSetters = new Dictionary<string, Action<T, object>>();<br /> You tin can then use a Set method to set the value of a property dynamically: <br /> public void Gear up(T obj, string propName, object value)<br /> {<br /> propSetters[propName](obj, value);<br /> }<br /> | | | | I am creating new PropertyAccessor objects in a loop at the charge per unit of about 100 per minute or and then. My pagefile grows at a pretty brisk pace until it overwhelms my calculator. This is in conjunction with table adapters for a data processing application. when I comment out (Property Adapter) pa.Set(...) in all 18 places, this no longer happens. I approximate its the assemblies are being cached at that place. How do I remove them? | | | | If y'all're non already doing and then, I would recommend caching PropertyAccessors so that you never create more than 1 instance for a given property of a Type. Actually, without doing this, the PropertyAccessor class would exist slower than reflection. If caching the PropertyAccessor is not feasible for your particular application, you tin unload the cached property assemblies by creating the PropertyAccessors and performing your operations within a new AppDomain. When washed with the processing, you tin can then unload that app domain and the assemblies created under it. Still, this introduces code complexity and you'd have to utilize Remoting to communicate across the AppDomain boundaries. | | | | Hullo, I have been using this code snippet & it worked perfect in .cyberspace 1.0 & 1.one. But ever since I ported to 2.0 there is a strange problem: AssemblyBuilder newAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);<br /> ModuleBuilder newModule = newAssembly.DefineDynamicModule(" Module");<br /> TypeBuilder myType = newModule.DefineType(" Holding", TypeAttributes.Public); It throws exception in DefineType . Say this lawmaking is executed 200 time. It will run fine 199 times but one time it volition throw exception. Only it will surely throw exception everytime I run. And it throws exception only when I debug using VS2005 non when I direct run. Does anyone have any clue to this problem. thanks, Mandeep. | | | | Hullo at that place! First of all - wow, James, that'southward fantabulous work! I have never used Emit before - and hither it really makes so much sense! I am using VS 2005 - so I thought, I could do a quick port to .Internet 2.0, merely to learn something virtually Emit. Turns out, information technology is tragically easy to implement it using generics. That is, implementing it using your great lawmaking. Seriously, information technology boils down to removing the casting stuff in your code. Simply those easy modification give you an additional speed boost and actually cuts the become and set on value types in one-half! And in that location is even so a meaning speed gain on regular objects too. Have fun downloading GenericPropertyAccessor from my blog, plus an updated examination app. For those too lazy to click on the link in my blog - here is the direct link: GenericPropertyAccessor as Zero Have fun, Tobi P.S.: I have no idea, what to put in the header of these files?! How exercise I "conspicuously marking" that I inverse the code but hugely depended on James' piece of work? Is what I did ok, or should I change the header? Aid! --- Tobi + C# = T# | | | | First, I thank James very much for the cracking piece of work! Howdy Tobi, the Generic implemation is very squeamish. I couldn't pass the property types dynamically to the GenericPropertyAccessor. Eg: The below code works fine for cord type property. GenericPropertyAccessor<propertyaccessortestobject, string=""> propertyAccessor = new GenericPropertyAccessor<propertyaccessortestobject, <big="">string>("String"); but, I am using the above lawmaking in the iteration of a collection to display all the property values, then I should laissez passer the property type (higleted) dynamically. any help? LK. | | | | Hey Leela, I guess for your kind of situation you would take to use James' original PropertyAccessor. But actually I am not too sure if I sympathize the situation y'all are trying to solve. Sorry. Tobi --- Tobi + C# = T# | | | | Hi, swell work, I've been using it and information technology works fine, but I have a problem: did you ever try accessing properties from a value blazon? If you lot try, for case, to get the property "Width" from a System.Cartoon.Size, you lot don't get the value, merely a "strange" number that seems to be a memory address... I'g totally ignorant about Emit and I'1000 not able to see where the trouble is, did you lot verify the same problems and, if you did, practise you take some hints about it? Cheers, cheerio, Wasp | | | | Hi, this lawmaking will be actually helpful to me but i also demand getting name and value of all public properties. and i as well don't have enough noesis almost IL coding. i'll give Blazon and BindingFlags equally parameters instead of holding proper name, and it will give me property info collection. thanks for your help.. -- savas -- | | | | Given the code equally is and the reflection API (you lot already know about BindingFlags) this should be a like shooting fish in a barrel. Unless you need help coding arrays/collections...? | | | | How to brand better (example of reflection) this situation on C# // assembly1 form c1 { public void method1() {} public int method2() { return 100; } } // assembly2 class c2 { c1 _c1 = new c1(); c3 _c3 = new _c3(_c1); } // assembly3 form c3(object _o) { _o.method1(); int y = 100; y = y + _o.method2(); // 200 MessageBox.Evidence(y.ToString()); // 200 } | | | | This is nice stuff, but I take one trouble. When I try to set a null value I get a NullReferenceException when the type of the belongings is a ValueType. Is in that location a way to change the generated IL for the SetValue method so that it perfoms a null-check get-go and if and so, set the value to the initial value of a ValueType (for case, 0 for ints)? I tried fixing it myself but the IL language is very difficult. Cheers. Pat | | | | Rather than put this logic in the IL of the emitted property accessor, y'all could place it in the Set method of the physical PropertyAccessor (see code beneath). It might fifty-fifty make sense to make the PropertyAccessor a base class with a protected abstract DefaultValue belongings. You could create a concrete implementation for each value type, merely then y'all would also need a manufactory to create the appropriate belongings accessor... public void Set up(object target, object value) { if(mCanWrite) { if(this.mEmittedPropertyAccessor == null) { this.Init(); } object newValue = value; if(newValue == null && PropertyType.IsValueType) { newValue = DefaultValue; } this.mEmittedPropertyAccessor.Set(target, newValue); } else { throw new PropertyAccessorException(string.Format(" Property \"{0}\" does" + " non have a prepare method.", mProperty)); } } James | | | | James, nice work. Information technology was *almost* what i needed. I had the aforementioned use-case regarding public fields instead of backdrop. So I sat down and refactored a flake thank you, it refactored just fine (which compliments your style). I factored out an (abstract) base course MemberAccessor, which has 2 descendants, FieldAccessor and PropertyAccessor, obviously. The descendants sole task is to implement EmitSetter() and EmitGetter() (which are abstract methods on the baseclass. I even saturday downward and refactored the tests. All tests relevant to both fields and methods have moved into a baseclass MemberAccessorTest, and the derived TestFixtures PropertyAccessorTest/FieldAccesorTest extend this with specific tests (e.g. there is no such matter as a WriteOnly field, and no such thing every bit a 'const' property). Obviously at that place has been major discover/replace Property->Member to keep the naming consistent with the purposes (e.chiliad. IMemberAccessor instead of IPropertyAccessor). The icing on the cake may be a manufacturing plant method MemberAccessor.Make(...) which will instantiate either a PropertyAccessor or FieldAccessor by reflection. If you are interested i volition send/upload (?) the extended project 'FastDynamicMemberAccessor.proj'. PS1. performance might have gone up by a chance to EmitAssembly that creates a 'sealed' class (gives compiler a huge optimization clue) PS2. yeah I apply public fields for simple XmlSerializer-able classes PS3. Needless to say, SampleApp runs without modification PS4. The sharing of 36 test cases across the field/belongings variants has been achieved by implementing PropertyAccessorTestObject/FieldAccessorTestObject with a shared interface IMemberAccessorTestObject that interface is *merely* used for test asserts, not for member access, of course | | | | | |
0 Response to "Dynamically Reading a Class Property in C#"
Post a Comment