generic function with a "has property X" constraint? - c#

I have a third-party, closed source application that exports a COM interface, which I am using in my C#.NET application through Interop. This COM interface exports many objects that all show up as System.Object until I cast them to the appropriate interface type. I want to assign an property of all of these objects. Thus:
foreach (object x in BigComInterface.Chickens)
{
(x as Chicken).attribute = value;
}
foreach (object x in BigComInterface.Ducks)
{
(x as Duck).attribute = value;
}
But assigning the property is likely (for application-specific reasons that are unavoidable) to throw Exceptions from which I want to recover, so I really want a try/catch around each one. Thus:
foreach (object x in BigComInterface.Chickens)
{
try
{
(x as Chicken).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
foreach (object x in BigComInterface.Ducks)
{
try
{
(x as Duck).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
Obviously, it would be so much cleaner to do this:
foreach (object x in BigComInterface.Chickens)
{
SetAttribute<Chicken>(x as Chicken, value);
}
foreach (object x in BigComInterface.Ducks)
{
SetAttribute<Duck>(x as Duck, value);
}
void SetAttribute<T>(T x, System.Object value)
{
try
{
x.attribute = value;
}
catch
{
// handle...
}
}
See the problem? My x value can be of any type, so the compiler can't resolve .attribute. Chicken and Duck are not in any kind of inheritance tree and they do not share an interface that has .attribute. If they did, I could put a constraint for that interface on T. But since the class is closed-source, that's not possible for me.
What I want, in my fantasy, is something like a constraint requiring the argument to have the .attribute property regardless of whether it implements a given interface. To wit,
void SetAttribute<T>(T x, System.Object value) where T:hasproperty(attribute)
I'm not sure what to do from here other than to cut/paste this little try/catch block for each of Chicken, Duck, Cow, Sheep, and so on.
My question is: What is a good workaround for this problem of wanting to invoke a specific property on an object when the interface that implements that property cannot be known at compile time?

Well, depending on how humongous your exception handling code is (and if i am not mistaken it could be quite so) using the following trick might help you:
class Chicken
{
public string attribute { get; set; }
}
class Duck
{
public string attribute { get; set; }
}
interface IHasAttribute
{
string attribute { get; set; }
}
class ChickenWrapper : IHasAttribute
{
private Chicken chick = null;
public string attribute
{
get { return chick.attribute; }
set { chick.attribute = value; }
}
public ChickenWrapper(object chick)
{
this.chick = chick as Chicken;
}
}
class DuckWrapper : IHasAttribute
{
private Duck duck = null;
public string attribute
{
get { return duck.attribute; }
set { duck.attribute = value; }
}
public DuckWrapper(object duck)
{
this.duck = duck as Duck;
}
}
void SetAttribute<T>(T x, string value) where T : IHasAttribute
{
try
{
x.attribute = value;
}
catch
{
// handle...
}
}

Unfortunately, this is tricky currently. In C# 4, the dynamic type may help quite a bit with this. COM interop is one of the places that dynamic really shines.
However, in the meantime, the only option that allows you to have any type of object, with no restrictions on interfaces, would be to revert to using reflection.
You can use reflection to find the "attribute" property, and set it's value at runtime.

To not have to violate the DRY principle you can use reflection. If you really want to use generics, you could use a wrapper class for each type of 3rd party object and have the wrapper implement an interface that you can use to constrain the generic type argument.
An example of how it could be done with reflection. Code is not tested though.
void SetAttribute(object chickenDuckOrWhatever, string attributeName, string value)
{
var typeOfObject = chickenDuckOrWhatever.GetType();
var property = typeOfObject.GetProperty(attributeName);
if (property != null)
{
property.SetValue(chickenDuckOrWhatever, value);
return;
}
//No property with this name was found, fall back to field
var field = typeOfObject.GetField(attributeName);
if (field == null) throw new Exception("No property or field was found on type '" + typeOfObject.FullName + "' by the name of '" + attributeName + "'.");
field.SetValue(chickenDuckOrWhatever, value);
}
If you to speed up the code for performance, you could cache the FieldInfo and PropertyInfo per type of chickenDuckOrWhatever and consult the dictionary first before reflecting.
TIP: To not have to hardcode the attributeName as a string, you could use C# 6 feature nameof. Like nameof(Chicken.AttributeName) for example.

Unfortunately the only way to do this is to constrain the type parameter with an interface that defines that property and is implemented on all types.
Since you do not have the source this will be impossible to implement and as such you will have to use some sort of workaround. C# is statically typed and as such doesn't support the kind of duck-typing you want to use here. The best thing coming soon (in C# 4) would be to type the object as dynamic and resolve the property calls at execution time (note that this approach would also not be generic as you cannot constrain a generic type parameter as dynamic).

Related

Properly finding an inherited interface property through reflection

This is a two-part question. First, which of these explicit property implementations gets bound to IAllTogether.SomeInt and why doesn't the compiler complain about ambiguity? It does when you comment-out the marked lines.
public interface IFirst
{
int SomeInt { get; }
}
public interface ISecond
{
int SomeInt { get; }
}
public interface ICombined : IFirst, ISecond
{
new int SomeInt { get; } // Comment this line.
}
public interface IAllTogether : IFirst, ISecond, ICombined
{ }
public sealed class Implementation : IAllTogether
{
int ICombined.SomeInt { get { return 0; } } // Comment this line.
int IFirst.SomeInt { get { return 0; } }
int ISecond.SomeInt { get { return 0; } }
}
IAllTogether t = new Implementation();
var unimportant = t.SomeInt;
Second question would be: how do I find the right PropertyInfo when given an interface Type and a name of the property? I can use GetInterfaces() and GetProperty() to list all the possible candidates, but how do I know which is the right one? I tried typeof(IAllTogether).GetProperty("SomeInt"), but it doesn't work.
Edit
Looks like the answer to the first part is that the hiding of inherited members resolves ambiguity. However, not even a single comment yet on the second part: how to reliably find the proper PropertyInfo for some property name and an interface type.
Edit 2
Clarification on the second part of the question. What I'm looking for is a way to get the right property for any unknown Type. Basically, a method like this:
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (!interfaceType.IsInterface)
throw new ArgumentException();
// for interfaceType == typeof(IAllTogether), return ICombined.SomeInt
// for interfaceType == typeof(IFirst), return IFirst.SomeInt
}
Lots of people answered the first part: if an interface hides members of the original interface, those are not considered.
Using that information, here's my attempt at the second part. Comments on issues or improvements are welcome.
public static PropertyInfo GetPropertyOfInterface(Type interfaceType, string propertyName)
{
if (interfaceType == null)
throw new ArgumentNullException("interfaceType");
if (!interfaceType.IsInterface)
throw new ArgumentException(
string.Format("Type {0} doesn't represent an interface.",
interfaceType.FullName),
"interfaceType");
// If declared in given interface, just return that.
var declaredProperty = interfaceType.GetProperty(propertyName);
if (declaredProperty != null)
return declaredProperty;
// Otherwise, first finding all the candidates.
var candidates = new HashSet<PropertyInfo>(
interfaceType.GetInterfaces().Select(t => t.GetProperty(propertyName)));
candidates.Remove(null);
if (candidates.Count == 0)
throw new ArgumentException(
string.Format("Property {0} not found in interface {1}.",
propertyName, interfaceType.FullName),
"propertyName");
// Finally, removing all candidates the first candidates hide.
var originalCandidates = candidates.ToList();
candidates.ExceptWith(
originalCandidates.SelectMany(prop => prop.DeclaringType.GetInterfaces())
.Select(t => t.GetProperty(propertyName)));
if (candidates.Count != 1)
throw new AmbiguousMatchException(
string.Format("Property {0} is ambiguous in interface {1}.",
propertyName, interfaceType.FullName));
return candidates.First();
}
To answer your first question.
Compiler only need to know is that the interface members are implemented or not. It is the runtime who decides which version of the member to invoke.
In your example you are using explicit implementation.
In this case compile first checks if SomeInt property is implemented or not. If that is implicitly implemented it won't complain. If any one of the interface property is implemented explicitly compiler will check if rest o the interface properties are implemented either by implicit or explicit.

Syntax for implicit operator with class indexer

I am looking for the correct syntax to use an implicit operator on a class that uses an indexer to acess a private Dictionary:
[System.Serializable]
public class MyClass : IEnumerable
{
private Dictionary<string, object> vars = new Dictionary<string, object>();
public object this[string key]
{
get
{
if(vars.ContainsKey(key))
{
return (object)vars[key];
}
else
{
return null;
}
}
set
{
object o = value;
if(!vars.ContainsKey(key))
{
vars.Add(key, o);
}
else if(value == null)
{
vars.Remove(key);
}
else
{
vars[key] = o;
}
}
}
/*some code*/
public static implicit operator bool(WorldVars w, string i)
{
if(w[i] != null)
{
return true;
}
else
{
return false;
}
}
}
Right now the use is pretty straight forward
MyClass[anykey] = myValue
but I'd like to implement a quicker way to test the presence of a value, like:
if(MyClass[anykey])
{ //logic }
As commenter Eric notes, the semantics of your class would be completely broken if you were able to achieve what you're asking for. The whole point of the indexer is so that when you write the expression myClass[anyKey], it evaluates to the value that your class associates with anyKey.
If you were to change the implementation so that it simply returned a bool value representing containment, then you'd be stuck having to implement some other mechanism to actually retrieve the value (e.g. a separate method). Additionally, it would also raise the question of what the setter should do.
Given the implementation you show, it seems to me that writing if (myClass[anyKey] != null) is not really inconvenient, and it seems reasonably expressive to me. That is, it is a reasonable way for the code to clearly express its intent.
That said, if you did want something more expressive, it would not be unreasonable to write a ContainsKey() method in your class for the purpose:
public bool ContainsKey(string key) { return vars.ContainsKey(key); }
Then you could check for the key's presence like:
if (myClass.ContainsKey[anyKey]) { ... }
Finally, the code you posted should work acceptably well, but it seems overly verbose and inconsistent to me. IMHO, a better way to write your indexer methods would be something like this:
public object this[string key]
{
get
{
object o;
return vars.TryGetValue(key, out o) ? o : null;
}
set
{
if (value != null)
{
vars[key] = value;
}
else
{
vars.Remove(key);
}
}
}
That implementation avoids things like:
Redundant check for containment when getting a value
Copying value into local variable unnecessarily when setting a value
Having two different lines of code that each both have the effect of setting the value for a key in the dictionary

C# Generics - Constraining types to those that implement a property or field [duplicate]

I have a third-party, closed source application that exports a COM interface, which I am using in my C#.NET application through Interop. This COM interface exports many objects that all show up as System.Object until I cast them to the appropriate interface type. I want to assign an property of all of these objects. Thus:
foreach (object x in BigComInterface.Chickens)
{
(x as Chicken).attribute = value;
}
foreach (object x in BigComInterface.Ducks)
{
(x as Duck).attribute = value;
}
But assigning the property is likely (for application-specific reasons that are unavoidable) to throw Exceptions from which I want to recover, so I really want a try/catch around each one. Thus:
foreach (object x in BigComInterface.Chickens)
{
try
{
(x as Chicken).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
foreach (object x in BigComInterface.Ducks)
{
try
{
(x as Duck).attribute = value;
}
catch (Exception ex)
{
// handle...
}
}
Obviously, it would be so much cleaner to do this:
foreach (object x in BigComInterface.Chickens)
{
SetAttribute<Chicken>(x as Chicken, value);
}
foreach (object x in BigComInterface.Ducks)
{
SetAttribute<Duck>(x as Duck, value);
}
void SetAttribute<T>(T x, System.Object value)
{
try
{
x.attribute = value;
}
catch
{
// handle...
}
}
See the problem? My x value can be of any type, so the compiler can't resolve .attribute. Chicken and Duck are not in any kind of inheritance tree and they do not share an interface that has .attribute. If they did, I could put a constraint for that interface on T. But since the class is closed-source, that's not possible for me.
What I want, in my fantasy, is something like a constraint requiring the argument to have the .attribute property regardless of whether it implements a given interface. To wit,
void SetAttribute<T>(T x, System.Object value) where T:hasproperty(attribute)
I'm not sure what to do from here other than to cut/paste this little try/catch block for each of Chicken, Duck, Cow, Sheep, and so on.
My question is: What is a good workaround for this problem of wanting to invoke a specific property on an object when the interface that implements that property cannot be known at compile time?
Well, depending on how humongous your exception handling code is (and if i am not mistaken it could be quite so) using the following trick might help you:
class Chicken
{
public string attribute { get; set; }
}
class Duck
{
public string attribute { get; set; }
}
interface IHasAttribute
{
string attribute { get; set; }
}
class ChickenWrapper : IHasAttribute
{
private Chicken chick = null;
public string attribute
{
get { return chick.attribute; }
set { chick.attribute = value; }
}
public ChickenWrapper(object chick)
{
this.chick = chick as Chicken;
}
}
class DuckWrapper : IHasAttribute
{
private Duck duck = null;
public string attribute
{
get { return duck.attribute; }
set { duck.attribute = value; }
}
public DuckWrapper(object duck)
{
this.duck = duck as Duck;
}
}
void SetAttribute<T>(T x, string value) where T : IHasAttribute
{
try
{
x.attribute = value;
}
catch
{
// handle...
}
}
Unfortunately, this is tricky currently. In C# 4, the dynamic type may help quite a bit with this. COM interop is one of the places that dynamic really shines.
However, in the meantime, the only option that allows you to have any type of object, with no restrictions on interfaces, would be to revert to using reflection.
You can use reflection to find the "attribute" property, and set it's value at runtime.
To not have to violate the DRY principle you can use reflection. If you really want to use generics, you could use a wrapper class for each type of 3rd party object and have the wrapper implement an interface that you can use to constrain the generic type argument.
An example of how it could be done with reflection. Code is not tested though.
void SetAttribute(object chickenDuckOrWhatever, string attributeName, string value)
{
var typeOfObject = chickenDuckOrWhatever.GetType();
var property = typeOfObject.GetProperty(attributeName);
if (property != null)
{
property.SetValue(chickenDuckOrWhatever, value);
return;
}
//No property with this name was found, fall back to field
var field = typeOfObject.GetField(attributeName);
if (field == null) throw new Exception("No property or field was found on type '" + typeOfObject.FullName + "' by the name of '" + attributeName + "'.");
field.SetValue(chickenDuckOrWhatever, value);
}
If you to speed up the code for performance, you could cache the FieldInfo and PropertyInfo per type of chickenDuckOrWhatever and consult the dictionary first before reflecting.
TIP: To not have to hardcode the attributeName as a string, you could use C# 6 feature nameof. Like nameof(Chicken.AttributeName) for example.
Unfortunately the only way to do this is to constrain the type parameter with an interface that defines that property and is implemented on all types.
Since you do not have the source this will be impossible to implement and as such you will have to use some sort of workaround. C# is statically typed and as such doesn't support the kind of duck-typing you want to use here. The best thing coming soon (in C# 4) would be to type the object as dynamic and resolve the property calls at execution time (note that this approach would also not be generic as you cannot constrain a generic type parameter as dynamic).

How can I make this code with enumerations generic?

I am creating the wrapper POCO classes for ENUM in Entity Framework 4 as mentioned here. I have created the wrapper for the enum as follows
public class PriorityWrapper
{
private gender _t;
public int Value
{
get
{
return (int)_t;
}
set
{
_t = (gender)value;
}
}
public gender EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public static implicit operator PriorityWrapper(gender p)
{
return new PriorityWrapper { EnumValue = p };
}
public static implicit operator gender(PriorityWrapper pw)
{
if (pw == null) return gender.Male;
else return pw.EnumValue;
}
}
But I also have other ENUM apart from gender as mentioned above. Can I use generics here so I can use the same code for all ENUM occurrences.
I am new to generics, so need help from experts.
You cannot use enums as generic constraints, instead you can use.
public class EnumWrapper<T>
{
public static int Num = 1;
private T _t;
public T EnumValue
{
get
{
return _t;
}
set
{
_t = value;
}
}
public void Assign<U>(U inn) where U : struct, T
{
if (typeof(T).IsEnum)
{
EnumValue = inn;
}
}
}
and invoke it like this
var agen = new EnumWrapper<gender>();
gender g=new gender() ;
agen.Assign (g);
EDIT: Assign() is a dummy method. My intention was to show how to use enum as generic constraint.
It is not possible to have generic conversion operators. So, there can't be exact generic equivalent for above code. Besides, one cannot mention enum as generic type constraint, so casting within property implementation is also not possible (or may need some other constraint (possibly interface) to work that may result in boxing/unboxing). In short, IMO, having generic solution with reasonable performance may not be feasible.
I would suggest that you try using code generation (look at T4 templates) for creating your wrapper classes. T4 is pretty simple - refer here for few links: http://www.hanselman.com/blog/T4TextTemplateTransformationToolkitCodeGenerationBestKeptVisualStudioSecret.aspx

Fallback accessors in C#?

Does C# have anything like Python's __getattr__?
I have a class with many properties, and they all share the same accessor code. I would like to be able to drop the individual accessors entirely, just like in Python.
Here's what my code looks like now:
class Foo
{
protected bool Get(string name, bool def)
{
try {
return client.Get(name);
} catch {
return def;
}
}
public bool Bar
{
get { return Get("bar", true); }
set { client.Set("bar", value); }
}
public bool Baz
{
get { return Get("baz", false); }
set { client.Set("baz", value); }
}
}
And here's what I'd like:
class Foo
{
public bool Get(string name)
{
try {
return client.Get(name);
} catch {
// Look-up default value in hash table and return it
}
}
public void Set(string name, object value)
{
client.Set(name, value)
}
}
Is there any way to achieve this in C# without calling Get directly?
Thanks,
No. Although C# supports reflection, it is read-only (for loaded assemblies). That means you can't change any methods, properties, or any other metadata. Although you could create a dynamic property, calling it wouldn't be very convenient - it would be even worse than using your Get method. Aside from using a Dictionary<string, object> and an indexer for your class, there's not much else you can do. Anyway, isn't doing a dictionary better if you have that many properties?
Python doesn't check if an attribute exists at "compile-time" (or at least load-time). C# does. That's a fundamental difference between the two languages. In Python you can do:
class my_class:
pass
my_instance = my_class()
my_instance.my_attr = 1
print(my_instance.my_attr)
In C# you wouldn't be able to do that because C# actually checks if the name my_attr exists at compile-time.
I'm not sure, but perhaps the dynamic features of version 4.0 will help you with that. You'll have to wait though...
Can I ask: why don't you want the individual properties? That is the idiomatic .NET way of expressing the data associated with an object.
Personally, assuming the data isn't sparse, I would keep the properties and have the overall method use reflection - this will make your compiled code as fast as possible:
protected T Get<T>(string name, T #default)
{
var prop = GetType().GetProperty(name);
if(prop == null) return #default;
return (T) prop.GetValue(this, null);
}
Of course, if you don't care about the properties themselves being defined, then an indexer and lookup (such as dictionary) would be OK. There are also things you might be able to do with postsharp to turn a set of properties into a property-bag - probably not worth it, though.
If you want the properties available for data-binding and runtime discovery, but can't define them at compile-time, then you would need to look at dynamic type descriptors; either ICustomTypeDescriptor or TypeDescriptionProvider - a fair bit of work, but very versatile (let me know if you want more info).
This is not the same as what you get in Python with dynamic property names, but you might find it useful:
using System;
using System.Collections.Generic;
namespace Program
{
class Program
{
static void Main(string[] args)
{
MyList<int> list = new MyList<int>();
// Add a property with setter.
list["One"] = 1;
// Add a property with getter which takes default value.
int two = list["Two", 2];
Console.WriteLine("One={0}", list["One"]);
Console.WriteLine("Two={0} / {1}", two, list["Two"]);
try
{
Console.WriteLine("Three={0}", list["Three"]);
}
catch
{
Console.WriteLine("Three does not exist.");
}
}
class MyList<T>
{
Dictionary<string, T> dictionary = new Dictionary<string,T>();
internal T this[string property, T def]
{
get
{
T value;
if (!dictionary.TryGetValue(property, out value))
dictionary.Add(property, value = def);
return value;
}
}
internal T this[string property]
{
get
{
return dictionary[property];
}
set
{
dictionary[property] = value;
}
}
}
}
}

Categories

Resources