Can I access object properties as a type?
I am using an API where I have to iterate through a collection of objects, and access the Text properties of two of these objects, either for reading or for writing. I currently have two methods for reading and writing as follows:
Result ReadTexts()
var attribs = SOME_CODE;
string first = "", second = "";
for(int i=1 ; i <= attribs.Count ; i++) {
if(attribs[i] IS_FIRST_ONE_NEEDED) {
first = attribs[i].Text;
} else if(attribs[i] IS_SECOND_ONE_NEEDED) {
second = attribs[i].Text;
}
}
return new Result(first, second);
}
void WriteTexts(string first, string second) {
var attribs = SOME_CODE;
for(int i=1 ; i <= attribs.Count ; i++) {
if(attribs[i] IS_FIRST_ONE_NEEDED) {
attribs[i].Text = first;
} else if(attribs[i] IS_SECOND_ONE_NEEDED) {
attribs[i].Text = second;
}
}
}
What I would prefer is using a more functional style which factors out the iteration and checking for the two objects in the collection into one method instead of repeating this code, as actually SOME_CODE as well as IS_FIRST_ONE_NEEDED and IS_SECOND_ONE_NEEDED are a bit longer in reality than in the above sample code. This one method would look like:
void AccessTexts(Action<StringProperty> first, Action<StringProperty> second) {
var attribs = SOME_CODE;
for(int i=1 ; i <= attribs.Count ; i++) {
if(attribs[i] IS_FIRST_ONE_NEEDED) {
first(attribs[i].Text);
} else if(attribs[i] IS_SECOND_ONE_NEEDED) {
second(attribs[i].Text);
}
}
}
and then call this with lambda expressions like
AccessTexts(( prop => prop = "abc"), ( prop => prop = "def"));
for writing, or
AccessTexts(( prop => firstString = prop), ( prop => secondString = prop));
for reading. This would be much shorter and avoid repeating a lot of code.
But I think this is not possible, as properties are not exposed as a real type in .net, but are just based on the availability of special methods - the getter and setter. Hence, there is no type StringProperty as I used it as type of the delegate parameter in the code sample of "what I would like to write".
Am I right, or is there some way to implement it the way I want?
You can create your own class that represents a property. As you've shown, a property is essentially just a get and set method, so that's all our class needs to represent.
As for how to create such a thing, one option is to have the type accept a getter and setter as delegates directly. Another option is to have it accept a PropertyInfo and an object which can then use reflection to implement the getter and setter methods. Finally, if you wanted to, you could even use an Expression to represent the property access, and then pull out the PropertyInfo from that.
So to start out with, the actual wrapper itself:
public class PropertyWrapper<T>
{
private Func<T> getter;
private Action<T> setter;
public PropertyWrapper(PropertyInfo property, object instance)
{
if (!typeof(T).IsAssignableFrom(property.PropertyType))
throw new ArgumentException("Property type doesn't match type supplied");
setter = value => property.SetValue(instance, value);
getter = () => (T)property.GetValue(instance);
}
public PropertyWrapper(Func<T> getter, Action<T> setter)
{
this.setter = setter;
this.getter = getter;
}
public T Get()
{
return getter();
}
public void Set(T value)
{
setter(value);
}
public T Value
{
get { return getter(); }
set { setter(value); }
}
}
You can then use a helper such as this (it's extracted out of the other class so that there is generic type inference:
public class PropertyWrapper
{
public static PropertyWrapper<TProp> Create<TObject, TProp>(
TObject instance, Expression<Func<TObject, TProp>> expression)
{
var memberEx = expression.Body as MemberExpression;
var prop = memberEx.Member as PropertyInfo;
return new PropertyWrapper<TProp>(prop, instance);
}
}
Here is a simple example of constructing such an object using the two different syntaxes:
var list = new List<int>();
var prop1 = new PropertyWrapper<int>(
() => list.Capacity, cap => list.Capacity = cap);
var prop2 = PropertyWrapper.Create(list, l => l.Capacity);
prop2.Value = 42;
Console.WriteLine(list.Capacity); //prints 42
What you did is definitely workable. You are providing an accessor for the property in question to your function AccessTexts so that the function does not care how the access is done.
Normally, this would be solved using an interface implemented by the object being iterated over, or implemented by a wrapper class.
You can also use reflection or dynamic to do the access.
In any case you need a proxy between AccessTexts and the real objects.
Related
I have a class with quite a lot of properties and I need to post this class property names to a webservice.
Easy solution is just to create that array by hand, as in new[] {"Id", "Name", "Date", "etc"}.
But that's not fun, I would like to have intellisense support. So far I came up with creating an enum with all these properties, then having a helper function which takes array of these enums and calls .ToString() on each and adds to array.
Problem - quite an useless enum and if my class gets updated, I would need to manualy sync that enum with class properties.
Ideal solution in my mind would be to have something like LINQ extension method, where I could pass properties, something like with Select - ToPropertiesArray(x => {x.Id, X.Name, x.Date})
Am I just crazy and this cannot be done and is just plainly stupid? Or a suggestion on how to pass property names with some kind of IntelliSense support?
public class MyClass
{
public int Id{get;set;}
public string S{get;set;}
public double D{get;set;}
}
public static string[] GetPropsNamesArray<T>(Expression<Func<T,Object>> expr)
{
var t = GetObjectType(expr);
var res = t.GetProperties(BindingFlags.Instance|BindingFlags.Public)
.Select(pi => pi.Name)
.ToArray();
return res;
}
public static Type GetObjectType<T>(Expression<Func<T, object>> expr)
{
if ((expr.Body.NodeType == ExpressionType.Convert) ||
(expr.Body.NodeType == ExpressionType.ConvertChecked))
{
var unary = expr.Body as UnaryExpression;
if (unary != null)
return unary.Operand.Type;
}
return expr.Body.Type;
}
and use:
var selectedPropsNames = GetPropsNamesArray<MyClass>(m => new {m.Id,m.S});
var allPropsNames = GetPropsNamesArray<MyClass>(m => m);
As Lars said, you can use reflection. Using reflection in a method also gets you not having to rewrite when the properties collection changes. The beginning of a sample below iterates the public properties of an entity.
System.Reflection.PropertyInfo[] properties = entity.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach (System.Reflection.PropertyInfo propertyInfo in properties)
{
// ...
}
To have Intellisense support, you can use Expressions:
public static class Helper
{
public static List<string> ToPropertiesArray(params System.Linq.Expressions.Expression<Func<object>>[] exprs)
{
return exprs.Select(expr => ((expr.Body as System.Linq.Expressions.UnaryExpression).Operand
as System.Linq.Expressions.MemberExpression).Member.Name)
.ToList();
}
}
with sample usage:
SomeClass cl = new SomeClass();
var types = Helper.ToPropertiesArray(() => cl.SomeField, () => cl.SomeOtherField);
Not exactly how sure how to title this question, so I hope the title works.
The question is, can I use something similar to implicit type syntax on method calls. For example, this is the implicit type syntax I am referring to:
var x = new Y(){Foo = "Bar", Id = 1};
And I want to do something like this:
var x = myInstance.CreateItem(){Foo = "Bar", Id = 1};
Is there anything in C# that supports something like this? I don't want to do:
x.Foo = "Bar";
x.Id = 1;
...
Please note that CreateItem returns a dynamic type. The CreateItem method and its class cannot be modified.
I would settle for something similar to the With statement in VB.
Thanks in advance.
UPDATE: Attempting Mark Brackett's solution yielded this code:
TaskItem item = outlook.CreateItem(OlItemType.olTaskItem)._((Action<dynamic>)(i =>
{
i.Subject = "New Task";
i.StartDate = DateTime.Now;
i.DueDate = DateTime.Now.AddDays(1);
i.ReminderSet = false;
i.Categories = "#Work";
i.Sensitivity = OlSensitivity.olPrivate;
i.Display = true;
}));
...
public static class Extension
{
public static T _<T>(this T o, System.Action<dynamic> initialize) where T : class
{
initialize(o);
return o;
}
}
The only problem now is that the extension method doesn't seem to be binding to System._ComObject because I get this error: System._ComObject' does not contain a definition for '_'.
It's called an "object initializer", and no - it's not available for return values (or really, anytime other than with a new statement).
Syntax wise, about the closest I can think of would be to use an Action delegate (which requires changes to the Builder):
MyItem CreateItem(Action<MyItem> afterCreate) {
var i = new MyItem();
if (afterCreate != null) afterCreate(i);
return i;
}
var x = Builder.CreateItem(i => { i.Foo = "Bar"; i.Id = 1; });
If you're in a JavaScripty mood for short method names for commonly used functions, and can't change the Builder, I guess an extension method would also work:
public static T _<T>(this T o, Action<T> initialize) where T : class {
initialize(o);
return o;
}
var x = Builder.CreateItem()._(i => { i.Foo = "Bar"; i.Id = 1; });
Here's a twist for you. CreateItem() returns a dynamic type
Contrary to my comment, dynamic does require a few changes. You need to cast to object or the lambda will complain, and then you need to specify dynamic as T or it'll be inferred as object. Or, create your extension method with Action<dynamic> and no type arguments.
object CreateItem() {
return (object)Builder.CreateItem();
}
public static dynamic __(this object o, Action<dynamic> initialize) {
initialize(o);
return o;
}
var x = CreateItem().__(i => { i.Foo = "Bar"; i.Id = 1; });
You could use named arguments to the factory method:
public static Y Builder.CreateItem(string foo = "", int bar = 0)
{
return new Y() {Foo = foo, Bar = bar};
}
// called like so:
var x = Builder.CreateItem(Foo: "Bar", Id: 1);
You can specify 'public properties' in the constructor of the class but you cannot do that with methods
because
This rules only apply to member properties which is not possible with methods
You can not give public modofier in fields in the method so there is no possibility atall
When you do
var a = new MyClass{Foo="",Id=""};
You are defining properties of the class of this constructor MyClass()
You cannot do that with static or instance method
I've got some plain-old classes with a bunch of simple properties (simple {get; set;} declarations). All the properties are nullable (or equivalently, reference types).
For example:
class POCO
{
int? Field1 { get; set; }
string Field2 { get; set; }
... etc ...
}
I've got a scenario where I'm building these POCOs piecemeal, and at the end I'd like to get one of them with all the non-null fields.
Some illustrative code:
POCO o1 = LoadFields1To3();
POCO o2 = LoadFields4To5();
POCO o3 = LoadFields6To9();
... etc ...
We're in this scenario because some of the fields are loaded from SQL (and sometimes distinct queries), while some are loaded from in memory data structures. I'm re-using the POCO type here to avoid a bunch of otherwise pointless classes (a static type being quite useful for Dapper, and just in general).
What I'm looking for is a nice way to coalesce these objects' properties into a single one with the non-null properties.
Something like:
POCO final = o1.UnionProperties(o2).UnionProperties(o3) // and so on
I am able to guarantee that no field is non-null on more than one object. Though I'd assume a solution would take the left-most non-null field, it's not actually necessary.
I know I can write some reflection code to do this, but it's a bit nasty and slow.
This does need to be generically applicable, as while I never intend to coalesce objects of different types, there are a very large number of types that this method would be applicable to.
I was wondering if there isn't some cleverer way, perhaps abusing dynamic?
I gather (ok, I asked you) that the key objectives here are:
performance (reflection seeming too slow)
low maintenance (want to avoid a very manual copy-method, or complicated properties)
The following uses meta-programming to do whatever it can on the fly at runtime, compiling itself to a typed delegate (Action<POCO, POCO>) for efficient re-use:
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
public class SamplePoco
{
public int? Field1 { get; set; }
public string Field2 { get; set; }
// lots and lots more properties here
}
static class Program
{
static void Main()
{
var obj1 = new SamplePoco { Field1 = 123 };
var obj2 = new SamplePoco { Field2 = "abc" };
var merged = Merger.Merge(obj1, obj2);
Console.WriteLine(merged.Field1);
Console.WriteLine(merged.Field2);
}
}
static class Merger
{
public static T Merge<T>(params T[] sources) where T : class, new()
{
var merge = MergerImpl<T>.merge;
var obj = new T();
for (int i = 0; i < sources.Length; i++) merge(sources[i], obj);
return obj;
}
static class MergerImpl<T> where T : class, new()
{
internal static readonly Action<T, T> merge;
static MergerImpl()
{
var method = new DynamicMethod("Merge", null, new[] { typeof(T), typeof(T) }, typeof(T));
var il = method.GetILGenerator();
Dictionary<Type, LocalBuilder> locals = new Dictionary<Type, LocalBuilder>();
foreach (var prop in typeof(T).GetProperties())
{
var propType = prop.PropertyType;
if (propType.IsValueType && Nullable.GetUnderlyingType(propType) == null)
{
continue; // int, instead of int? etc - skip
}
il.Emit(OpCodes.Ldarg_1); // [target]
il.Emit(OpCodes.Ldarg_0); // [target][source]
il.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null); // [target][value]
il.Emit(OpCodes.Dup); // [target][value][value]
Label nonNull = il.DefineLabel(), end = il.DefineLabel();
if (propType.IsValueType)
{ // int? etc - Nullable<T> - hit .Value
LocalBuilder local;
if (!locals.TryGetValue(propType, out local))
{
local = il.DeclareLocal(propType);
locals.Add(propType, local);
}
// need a ref to use it for the static-call
il.Emit(OpCodes.Stloc, local); // [target][value]
il.Emit(OpCodes.Ldloca, local); // [target][value][value*]
var hasValue = propType.GetProperty("HasValue").GetGetMethod();
il.EmitCall(OpCodes.Call, hasValue, null); // [target][value][value.HasValue]
}
il.Emit(OpCodes.Brtrue_S, nonNull); // [target][value]
il.Emit(OpCodes.Pop); // [target]
il.Emit(OpCodes.Pop); // nix
il.Emit(OpCodes.Br_S, end); // nix
il.MarkLabel(nonNull); // (incoming) [target][value]
il.EmitCall(OpCodes.Callvirt, prop.GetSetMethod(), null); // nix
il.MarkLabel(end); // (incoming) nix
}
il.Emit(OpCodes.Ret);
merge = (Action<T, T>)method.CreateDelegate(typeof(Action<T, T>));
}
}
}
I'm creating a delayed function manager so that you can call TimeManager.DelayedCall(uniqueid, delay, action) to make action get invoked in delay seconds. However, I'm running into some trouble. Here's the code so far.
private static Dictionary<string, object> delays = new Dictionary<string, object>();
public static void Think(float dt)
{
timestep = dt * timescale;
time += timestep;
foreach (KeyValuePair<string, object> kv in delays)
{
if (time > kv.Value.ourtime)
{
kv.Value.action();
}
}
}
public static void DelayedCall(string id, float delay, Action a)
{
delays[id] = new { ourtime = time + delay, action = a };
}
This code doesn't compile. Because I'm converting the anonymous type from the DelayedCall function to an object, I cannot get the variables ourtime and action from it in the Think function! Does anyone know how to fix this, or how to do this in a better way?
EDIT Corrected some details here. See comment by Matti Virkkunen below.
Your anonymous type only has scope in the method where you create it. You cannot get the properties in the think function, because once you cast it into the object and save it in the dictionary the properties you set are gone. you cannot cast it back to the original type created by the compiler, so you cannot access the properties you set except indirectly via reflection.
Why do you need to use anonymous types and object type at all?
Based on the code posted I would just create a DelayData object that has all the properties you need to set, create and store instances of DelayData in the dictionary, and then use that object directly from the dictionary.
Well... You could always use reflection to access the fields in your object, but that's slow, and potentially ugly (although that last point is subjective). A cleaner version would involve dynamic objects (but then you lose type safety).
But why must you absolutely use an anonymous type? Can't you juste write a small wrapper class or struct, and then use that instead of object in your dictionary?
You can use reflection:
Action a = () => { Console.Write("Hello"); };
object o = new { ourtime = DateTime.Now, action = a };
DateTime ourtime = (DateTime) o.GetType().GetProperties()[0].GetValue(o, null);
Action action = (Action) o.GetType().GetProperties()[1].GetValue(o, null) ;
But it would be much cleaner to create a new type to hold these values i.e. TimedAction with two properties Time and Action
I'd get rid of the AnonymousType. It just makes things unclear, and the possibility for dorking up the values in the dictionary by adding the wrong type. I also added some Linq, and the use of List.ForEach.
public class Thing
{
public double ourtime;
public Action action;
}
public class Program
{
private readonly Dictionary<string, Thing> delays = new Dictionary<string, Thing>();
public void Think(float dt)
{
timestep = dt * timescale;
time += timestep;
var actions = delays.Where(d => time > d.Value.ourtime).Select(d => d.Value.action).ToList();
actions.ForEach(a => a());
}
public void DelayedCall(string id, float delay, Action a)
{
delays[id] = new Thing { ourtime = time + delay, action = a };
}
I'd write a tiny class with two properties and use that instead of an anonymous class. Another option is to switch to dynamic objects, and give up type safety.
http://msdn.microsoft.com/en-us/library/dd264736.aspx
Why not create a new type
class DelayAction
{
float OurTime;
Action a;
}
and change to
private static Dictionary<string, DelayAction> delays = new Dictionary<string, DelayAction>();
and
public static void DelayedCall(string id, float delay, Action a)
{
delays[id] = new DelayAction{ ourtime = time + delay, action = a };
}
I make extension method ToDictionary
object anonymous = new
{
Id = 1234,
Password = "pwd",
};
var dictionary = anonymous.ToDictionary();
and extension method was below.
public static IDictionary<string, dynamic> ToDictionary<T>(this T target, bool exceptDefaultValue = false)
where T : class
{
if (target == null)
{
throw new ArgumentNullException("target");
}
IDictionary<string, dynamic> dictionary = new Dictionary<string, dynamic>(System.StringComparer.OrdinalIgnoreCase);
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(target))
{
object value = propertyDescriptor.GetValue(target);
if (exceptDefaultValue == true)
{
if (value == null || value.Equals(propertyDescriptor.PropertyType.DefaultValue()) == true)
{
continue;
}
}
dictionary.Add(propertyDescriptor.Name, value);
}
return dictionary;
}
I want to build a method which accepts a string param, and an object which I would like to return a particular member of based on the param. So, the easiest method is to build a switch statement:
public GetMemberByName(MyObject myobj, string name)
{
switch(name){
case "PropOne": return myobj.prop1;
case "PropTwo": return myobj.prop2;
}
}
This works fine, but I may wind up with a rather large list... So I was curious if there's a way, without writing a bunch of nested if-else structures, to accomplish this in an indexed way, so that the matching field is found by index instead of falling through a switch until a match is found.
I considered using a Dictionary<string, something> to give fast access to the matching strings (as the key member) but since I'm wanting to access a member of a passed-in object, I'm not sure how this could be accomplished.
I'm specifically trying to avoid reflection etc in order to have a very fast implementation. I'll likely use code generation, so the solution doesn't need to be small/tight etc.
I originally was building a dictionary of but each object was initializing it. So I began to move this to a single method that can look up the values based on the keys- a switch statement. But since I'm no longer indexed, I'm afraid the continuous lookups calling this method would be slow.
SO: I am looking for a way to combine the performance of an indexed/hashed lookup (like the Dictionary uses) with returning particular properties of a passed-in object. I'll likely put this in a static method within each class it is used for.
Here's a quick mockup of something that could work for any class (using reflection rather than a switch statement):
public static object GetMemberByName<T>(T obj, string name)
{
PropertyInfo prop = typeof(T).GetProperty(name);
if(prop != null)
return prop.GetValue(obj, null);
throw new ArgumentException("Named property doesn't exist.");
}
Or an Extension Method version (which will still work on any object type):
public static object GetMemberByName<T>(this T obj, string name)
{
PropertyInfo prop = typeof(T).GetProperty(name);
if(prop != null)
return prop.GetValue(obj, null);
throw new ArgumentException("Named property doesn't exist.");
}
Obviously there's some additional error checking you might want to do, but this would be a start.
I also returned the type object from the methods for a reason. This allows the caller to handle casting the value however they see fit (if they need to cast at all).
Here's an easy way you can use a dictionary:
Dictionary<string, Func<MyObject, object>> propertyNameAssociations;
private void BuildPropertyNameAssociations()
{
propertyNameAssociations = new Dictionary<string, Func<MyObject, object>>();
propertyNameAssociations.Add("PropOne", x => x.prop1);
propertyNameAssociations.Add("PropTwo", x => x.prop2);
}
public object GetMemberByName(MyObject myobj, string name)
{
if (propertyNameAssociations.Contains(name))
return propertyNameAssociations[name](myobj);
else
return null;
}
There are a few options you can try.
Option 1: Have the object store the property values dynamically.
public GetMemberByName(MyObject myobj, string name)
{
return myobj.GetProperty(name);
}
public class MyObject
{
private Dictionary<string, object> m_Properties = new Dictionary<string, object>();
public object GetProperty(string name)
{
return m_Properties[name];
}
public void SetProperty(string name, object value)
{
m_Properties[name] = value;
}
public object Prop1
{
get { return GetProperty("PropOne"); }
set { SetProperty("PropOne", value); }
}
public object Prop2
{
get { return GetProperty("PropTwo"); }
set { SetProperty("PropTwo", value); }
}
}
Option 2: Use reflection.
public GetMemberByName(MyObject myobj, string name)
{
return typeof(MyObject).GetProperty(name).GetValue(obj, null);
}
Option 3: Leave it the way it is.
This is a reasonable option because switch statements on string data types will be converted to a Dictionary lookup once the number case statements reaches a certain threshold. That threshold is 7 on the C# 3.0 compiler. So the lookup will be O(1) no matter how many case statements there are. It will not scan through each one.
You can use reflection to get a property dynamically at runtime. Here is a snippet from a little relection utility i wrote. This is written as an extension method which would easily allow you to get a property from your class instance
myInstance.GetProperty<string>("Title"); // Replace 'string' with the proper return value.
The code:
public static class ReflectionExtensions
{
private const BindingFlags DefaultFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
public static T GetProperty<T>(this object instance, string propertyName)
{
PropertyInfo property = GetPropertyInfo(instance, propertyName);
if (property == null)
{
var message = string.Format("The Type, '{0}' does not implement a '{1}' property", instance.GetType().AssemblyQualifiedName, propertyName);
throw new NotImplementedException(message);
}
return (T)property.GetValue(instance, null);
}
private static PropertyInfo GetPropertyInfo(object instance, string propertyName)
{
Type type = instance.GetType();
return type.GetProperty(propertyName, DefaultFlags);
}
}
Well, assuming that the Name matches the actual name of the property (unlike your example), this would probably be best handled through reflection.
You cant do it with an index, but you could use reflection.
You may want to try using something like this.
private static readonly Dictionary<Type, Dictionary<string, PropertyInfo>> _cache = new Dictionary<Type,Dictionary<string,PropertyInfo>>();
public static T GetProperty<T>(object obj, string name)
{
if (obj == null)
{
throw new ArgumentNullException("obj");
}
else if (name == null)
{
throw new ArgumentNullException("name");
}
lock (_cache)
{
var type = obj.GetType();
var props = default(Dictionary<string, PropertyInfo>);
if (!_cache.TryGetValue(type, out props))
{
props = new Dictionary<string, PropertyInfo>();
_cache.Add(type, props);
}
var prop = default(PropertyInfo);
if (!props.TryGetValue(name, out prop))
{
prop = type.GetProperty(name);
if (prop == null)
{
throw new MissingMemberException(name);
}
props.Add(name, prop);
}
return (T)prop.GetValue(obj, null);
}
}