An object can provide its binding semantics by implementing
IDynamicMetaObject Provider—or more easily by subclassing
DynamicObject, which provides a default implementation of this
interface.
source
I never implemented this interface nor class and always been able to execute things dynamically:
public class aa
{
public void bbb()
{ }
}
dynamic a = new aa().bbb();
so what do they mean by this quote ?
im trying to understand when should i need to use IDynamicMetaObject or the DynamicObject inheritance
The dynamic keyword causes references to an object to be late-bound and only resolved at runtime. Usually, the reason for this is because you are using an IDynamicMetaObjectProvider implementer, which allows your code to decide how to treat the run-time property resolution. That is, you may want to add and remove properties at runtime (typically implemented as a dictionary, like ExpandoObject).
What your example code is doing is just preventing compile-type type checking. In fact it's worse than doing nothing, because if you wrote code that accessed a nonexistent property or method of your class, it would still compile, but of course crash at runtime. I can't think of many good reasons to refer to concrete classes with dynamic (expect for squishy typecasting or duck-typing, but we usually use interfaces for stuff like this in C#!)
Example implementation of a dynamic object that inherits DynamicObject from one of my own projects:
https://github.com/jamietre/IQObjectMapper/blob/master/source/IQObjectMapper/IQDynamicObject.cs
(It makes one call to a factory method that returns a new dictionary with options, all you need to do to make this non-dependent is change the constructor from:
InnerDict = ObjectMapper.MapperCache.GetDictionary<object>(Options);
to:
InnerDict = new Dictionary<string,object>();
and get rid of a couple conditons that check options
I hate to give "pithy" answers like this, because its not very imformative, but this really is a case of "if you needed it, you would know."
It is very rare that you would need to implement a dynamic object in an application, or even most library code. The interface is meant for people implementing classes that can only be used as dynamic objects; for example, if you wanted to implement Javascript-like behavior on your object. You can call any property or method you want on such an object, and it will compile. It's up to your implementation at run-time to figure out whether a given call works or not.
A totally pointless but descriptive example would be a class that decides which properties are valid based on the day of the week:
public class WeekendObject : DynamicObject
{
Dictionary<string, object> propertybag = new Dictionary<string, object>();
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
else
{
if (!name.StartsWith("Sunday"))
{
return propertybag.TryGetValue(name, out result);
}
}
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
if (DateTime.Now.DayOfWeek == DayOfWeek.Sunday)
{
if (name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
else
{
if (!name.StartsWith("Sunday"))
{
propertybag[binder.Name.ToLower()] = value;
return true;
}
}
return false;
}
}
Related
I am new to C#. I am trying to implement a Dictionary in C# whose Java-equivalent is:
HashMap<string, Variable<?>> dictionary
Here is the detailed Java version of what I'm trying to do: Java how to manage user-defined variables
In C# so far I have something like this:
interface IVariable { }
public class Variable<T> : IVariable
{
public T myValue { get; set; }
}
Dictionary<string, IVariable> vars = new Dictionary<string, IVariable>();
Then I try to do this:
Variable<int> age = new Variable<int>();
age.myValue = 12;
vars.Add("age", age);
IVariable theVar;
if (vars.TryGetValue("age", out theVar) {
Console.WriteLine("fetched age is " + theVar.myValue);
}
I run into trouble in the last line because the compiler doesn't recognize the myValue member of a theVar because it is an IVariable.
In this simple example maybe I could declare theVar to be a Variable<int> instead of an IVariable but I haven't tried it because it would require a priori knowledge about what kind of variable I'm fetching from the dictionary and I might not always have that knowledge.
I wouldn't mind if myValue were an inherited/abstract property (if there is such a thing), since every Variable will have a property named myValue (each will differ in type but not in name). In that case I guess I could make IVariable an abstract class rather than an interface, but then I still run into trouble as far as what to put for the type of myValue.
Could I do a cast of theVar into something using as by first checking its type with is? I'm not sure if that would work or is even possible.
I've looked at these posts for guidance (especially the second one):
Wildcard equivalent in C# generics
C# Generics: wildcards
However, my situation is still slightly different than the second example above because that example has an abstract method that is returning a void whereas I wish to have my variables return non-void generic values.
Thanks for any help.
C# has dynamic. You can create Dictionary<string, dynamic>
Or you can use object (boxing/unboxing) Dictionary<string, object>
Or you can get generic type from class
class MyClass<TDicValue>
{
Dictionary<strint, TDicValue> myDictionary;
}
I had this same problem where I had 20 slightly different types and I had to keep dictionaries on. I wanted to organize them in a list.
The problem was the same, selecting the right kind from the list with reflection or strings lacked the ability to provide a type to return to. #skrilmps answer is correct, but packing and and unpacking was at best unreliable without a lot (metric ton) of ugly messy code.
While unity does support dynamics in 2020, this doesn't exactly work with what i am doing unless I make like everything dynamic safe and that's shamble coding, not extensible or maintainable, and just sounds like a general nightmare.
I personally feel that I am an inadequate programmer after years of trying to learn and still not having my efforts provide a productive return or product of note, so i cannot claim the answer being mine, but in my research on the proper solution to this problem i found this: https://www.youtube.com/watch?v=A7qwuFnyIpM
In here he says basically if you add an interface to your similar classes that are intended for use in a variety of different lists, that you can instead make a list of that type of interface. I would assume dictionary as well, and then you can add any kind of class implementing this interface to this singular interface type defined list.
I tried using boxing/unboxing and came up with this solution. It appears to work... so far. But it doesn't seem very safe.
public interface Variable
{
object getValue();
void setValue(object value);
Type myType();
}
public class Variable<T>: Variable
{
private T myValue;
public object getValue()
{
return myValue;
}
public void setValue(object value)
{
myValue = (T)value;
}
public Type myType() { return myValue.GetType(); }
}
Dictionary<string, Variable> vars = new Dictionary<string, Variable>();
Variable<int> age = new Variable<int>();
age.setValue(21);
vars.Add("age", age);
Variable theAgeVar;
vars.TryGetValue("age", out theAgeVar);
Console.WriteLine("age = " + theAgeVar.getValue());
Variable<double> height = new Variable<double>();
height.setValue(5.9);
Variable theHeightVar;
vars.TryGetValue("age", out theHeightVar);
Debug.Log("height = " + theHeightVar.getValue());
This prints:
age = 21
height = 5.9
One thing I do not like is that I had to make the return type of getValue() be an object. If I wanted myValue (which is of type T) to implement IComparable, for instance, then this information is lost when the boxing happens and the caller receives an object.
// The following should resolve the boxing problem and now is totally generic:
public interface IVariable<T>
{
T GetContent();
void SetContent(T value);
Type GetDataType();
}
public class Variable<T> : IVariable
{
private T content;
public T GetContent()
{
return content;
}
public void SetContent(T value)
{
content = value;
}
public Type GetDataType() { return GetType(); }
}
Dictionary<string, Variable<T>> variables = new Dictionary<string, Variable<T>>();
I have a situation where a factory pattern seems appropriate like this:
enum Food {
Cake,
Cookies,
Milk,
CannedBeans
}
public static class FoodMetaDataFactory{
public static IFood GetMetaData(Food foodType){ //takes a food enum value as a parameter
switch(foodType){
case Food.Milk:
return new MilkMetaData();
case Food.CannedBeans:
return new CannedBeansMetaData();
case Food.Cookies:
return new CookiesMetaData();
case Food.Cake:
return new CakeMetaData();
}
}
}
However, I'd rather have more declarative pattern like this:
enum Food {
[FoodMetaDataAttribute(typeof(CakeMetaData))]
Cake,
[FoodMetaDataAttribute(typeof(CookiesMetaData))]
Cookies,
[FoodMetaDataAttribute(typeof(MilkMetaData))]
Milk,
[FoodMetaDataAttribute(typeof(CannedBeansMetaData))]
CannedBeans
}
public static class FoodMetaDataFactory{
public static IFood GetMetaData(Food foodType){ //takes a food enum value as a parameter
//reflectively retrieve FoodMetaDataAttribute
Type enumType = typeof(Food);
var memInfo = enumType.GetMember(foodType.ToString());
//assume one item returned
var foodMetaDataAttributes = memInfo[0].GetCustomAttributes(typeof(FoodMetaDataAttribute),
false);
// now access the property telling us the concrete type of the metadata class(this is the type passed in the attribute's declaration
Type targetType = ((FoodMetaDataAttribute)foodMetaDataAttributes[0]).MetaDataProviderType;
//not done yet, now we need to reflectively instantiate targetType, something like this
ConstructorInfo ctor = targetType.GetConstructor(new[] { });
//invoke the constructor, returning concrete instance such as CakeMetaData
return ctor.Invoke(new object[] {}) as IFood;
}
}
[AttributeUsage(AttributeTargets.Field)]
public class FoodMetaDataAttribute : Attribute
{
public FoodMetaDataAttribute(Type metaDataProviderType){
MetaDataProviderType = metaDataProviderType;
}
public Type MetaDataProviderType { get; set; }
}
I like this because it is clear to anyone adding new values to the enum that they need a meta data class and declare it in the attribute. This IMO is better than having to remember to modify the switch case in a factory.
It seemed simple at first until I started to think about the implementation of GetMetaData that has to reflectively retrieve the attribute, the typeof parameter, and then reflectively instantiate the MetaData class. I'm not experienced in creating attribute classes, so the primary driver of this question is a hope that maybe there's a simpler way to accomplish this with attributes. If attribute classes didn't have so many restrictions, such as on using generic types, I'd have this done in a way I liked with some compile time safety.
This proposed solution has no compile time safety. You can pass in types to the attribute that don't implement IFood, which is the minimum requirement for MetaData classes such as MilkMetaData. If attributes allowed generic type parameters I'd use that instead of typeof and could apply a where T:IFood
Is there a better way to utilize attributes to accomplish this mapping from enum value to concrete class?
What I usually do in these cases is create a dictionary of factories, e.g.:
private IDictionary<MyEnum, Func<IMyInterface>> Factories = new Dictionary<MyEnum, Func<IMyInterface>> {
{ MyEnum.MyValue, () => new MyType() },
// etc.
}
Simple and easy to maintain, extend or validate. You can create instance by doing:
IMyInterface instance;
if(!Factories.TryGetValue(enumValue, out instance))
throw new Exception(string.Format("No factory for enum value {0}", enumValue));
return instance;
Note that separating the enum from the actual instance should be a good thing (split implementation from data). Otherwise, I suggest you simply pass on the actual type to a generic method.
I'm not 100% sure that there is not a completely different approach that would be better, but there is just couple things you can improve in your current code:
You can use Activator.CreateInstance(type) instead of getting the constructor:
return Activator.CreateInstance(targetType) as IFood;
You can also consider some kind of cache, to avoid doing all the reflection-related work on every single call. You can either store a single instance of concrete IFood implementation for each enum value, using simple dictionary:
public static class FoodMetaDataFactory
{
private static Dictionary<Food, IFood> _cache = new Dictionary<Food, IFood>();
public static IFood GetMetaData(Food foodType)
{ //takes a food enum value as a parameter
IFood value;
if (!_cache.TryGetValue(foodType, out value))
{
lock (_cache)
{
if (!_cache.TryGetValue(foodType, out value))
{
var enumType = typeof(Food);
var memberInfo = enumType.GetMember(foodType.ToString());
var foodMetaDataAttributes = memberInfo[0].GetCustomAttributes(typeof(FoodMetaDataAttribute), false);
var targetType = ((FoodMetaDataAttribute)foodMetaDataAttributes[0]).MetaDataProviderType;
value = Activator.CreateInstance(targetType) as IFood;
_cache.Add(foodType, value);
}
}
}
return value;
}
}
or if you need each call to return fresh instance instead of shared one, you can use Expression Trees, to generate a Func<IFood> lambda expression when GetMetaData is called for the first time for given enum value, and call it later instead of reflection-processing.
About compile-time safety: I'm afraid you'd have to write your own custom check about that, e.g. as FxCop custom rule, or maybe something using Roslyn, if you're using newest (beta) version of Visual Studio.
New here. To start from the end, If you want to use these Enum values for display, the best way to do it is to decorate them with an attribute that is a display string (or CSV), but if the values need to be complex, you should be using a Factory Method that creates new Food types. A base class can contain common values while each successive Child class has specifics that can then always be fed to the UI mechanism.
This only works if either each type creates it's own View or the views are common between types. This is similar to dependency injection in the second idea.
But if you want to add additional enums that represent code paths, you have to ALWAYS update your Controller\ViewModel unless there is some generic model that is always used for display.
I don't know your code base, so I don't know what type of refactoring would be required for a Factory or Adapter pattern.
I'm creating a framework that contains a wrapper around a library (specifically SharpBrake) that performs all interaction with SharpBrake via reflection so there's no hard dependency on the library to 3rd parties of my framework.
If 3rd parties of my framework wants to use SharpBrake, they can just stuff the SharpBrake.dll into the bin folder, but if they don't, they can just forget about it. If my framework had explicit references to SharpBrake types, users of my framework would get exceptions during runtime of SharpBrake.dll missing, which I don't want.
So, my wrapper first loads SharpBrake.dll from disk, finds the AirbrakeClient type, and stores a delegate pointing to the AirbrakeClient.Send(AirbrakeNotice) method in a private field. My problem, however, is that since the Send() method takes an AirbrakeNotice object and I can't reference the AirbrakeNotice object directly, I need to somehow convert the Send() method to an Action<object>.
I have a strong feeling this isn't possible, but I want to explore all options before settling on exposing Delegate and using DynamicInvoke(), which I assume is far from optimal, performance-wise. What I would love to do is the following:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
MethodInfo sendMethod = clientType.GetMethod("Send", new[] { noticeType });
object client = Activator.CreateInstance(clientType);
Type actionType = Expression.GetActionType(noticeType);
Delegate sendMethodDelegate = Delegate.CreateDelegate(actionType, client, sendMethod);
// This fails with an InvalidCastException:
Action<object> sendAction = (Action<object>)sendMethodDelegate;
However, this fails with the following exception:
System.InvalidCastException: Unable to cast object of type 'System.Action`1[SharpBrake.Serialization.AirbrakeNotice]' to type 'System.Action`1[System.Object]'.
Obviously, because sendMethodDelegate is an Action<AirbrakeNotice> and not an Action<object>. Since I can't mention AirbrakeNotice in my code, I'm forced to do this:
Action<object> sendAction = x => sendMethodDelegate.DynamicInvoke(x);
or just exposing the Delegate sendMethodDelegate directly. Is this possible? I know that there's chance of getting into situations where the object can be of a different type than AirbrakeNotice which would be bad, but seeing how much you can mess up with reflection anyway, I'm hoping there's a loophole somewhere.
If you're happy to use expression trees, it's reasonably simple:
ConstantExpression target = Expression.Constant(client, clientType);
ParameterExpression parameter = Expression.Parameter(typeof(object), "x");
Expression converted = Expression.Convert(parameter, noticeType);
Expression call = Expression.Call(target, sendMethod, converted);
Action<object> action = Expression.Lambda<Action<object>>(call, parameter)
.Compile();
I think that's what you want...
If you don't need below C# 4 support you can get much greater performance using the dynamic vs DynamicInvoke.
Action<dynamic> sendAction = x => sendMethodDelegate(x);
Actually I guess you wouldn't even need the above if you can use dynamic, because it would increase performance and simplify everything if you just did:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
dynamic client = Activator.CreateInstance(clientType);
...
client.Send(anAirbrakeNotice);
But if you need to support .net 3.5 jon skeets answer with expression trees is definitely the way to go.
From my comment on the OP:
I'd avoid extended use of reflections if you are concerned about performance. If you can come up with an interface for the class(es) you are using, then I'd create one. Then write a wrapper that implements the interface by calling into the SharpBreak code, and stuff it in a separate DLL. Then dynamically load just your wrapper assembly and concrete wrapper type(s), and call into that interface. Then you don't have to do reflections at a method level.
I'm not sure all the classes you'd need, but here's a simple example of how you can hook into that library with loose coupling based on interfaces.
In your program's assembly:
public IExtensions
{
void SendToAirbrake(Exception exception);
}
public static AirbreakExtensions
{
private static IExtensions _impl;
static()
{
impl = new NullExtensions();
// Todo: Load if available here
}
public static void SendToAirbrake(this Exception exception)
{
_impl.SendToAirbrake(exception);
}
}
internal class NullExtensions : IExtensions // no-op fake
{
void SendToAirbrake(Exception exception)
{
}
}
In a load-if-available (via reflections) assembly
public ExtensionsAdapter : IExtensions
{
void SendToAirbrake(Exception exception)
{
SharpBrake.Extensions.SendToAirbrake(exception);
}
}
The advantage of this approach is that you only use reflections once (on load), and never touch it again. It is also simple to modify to use dependency injection, or mock objects (for testing).
Edit:
For other types it will take a bit more work.
You might need to use the Abstract Factory pattern to instantiate an AirbrakeNoticeBuilder, since you need to deal directly with the interface, and can't put constructors in interfaces.
public interface IAirbrakeNoticeBuilderFactory
{
IAirbrakeNoticeBuilder Create();
IAirbrakeNoticeBuilder Create(AirbrakeConfiguration configuration);
}
If you're dealing with custom Airbreak structures, you'll have even more work.
E.g. for the AirbrakeNoticeBuilder you will have to create duplicate POCO types for any related classes that you use.
public interface IAirbrakeNoticeBuilder
{
AirbrakeNotice Notice(Exception exception);
}
Since you're returning AirbrakeNotice, you might have to pull in nearly every POCO under the Serialization folder, depending on how much you use, and how much you pass back to the framework.
If you decide to copy the POCO code, including the whole object tree, you could look into using AutoMapper to convert to and from your POCO copies.
Alternately, if you don't use the values in the classes you're getting back, and just pass them back to the SharpBreak code, you could come up with some sort of opaque reference scheme that will use a dictionary of your opaque reference type to the actual POCO type. Then you don't have to copy the whole POCO object tree into your code, and you don't need to take as much runtime overhead to map the object trees back and forth:
public class AirbrakeNotice
{
// Note there is no implementation
}
internal class AirbreakNoticeMap
{
static AirbreakNoticeMap()
{
Map = new Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice>();
}
public static Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice> Map { get; }
}
public interface IAirbrakeClient
{
void Send(AirbrakeNotice notice);
// ...
}
internal class AirbrakeClientWrapper : IAirbrakeClient
{
private AirbrakeClient _airbrakeClient;
public void Send(AirbrakeNotice notice)
{
SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice];
_airbrakeClient.Send(actualNotice);
}
// ...
}
internal class AirbrakeNoticeBuilderWrapper : IAirbrakeNoticeBuilder
{
AirbrakeNoticeBuilder _airbrakeNoticeBuilder;
public AirbrakeNotice Notice(Exception exception)
{
SharpBreak.AirbrakeNotice actualNotice =
_airbrakeNoticeBuilder.Notice(exception);
AirbrakeNotice result = new AirbrakeNotice();
AirbreakNoticeMap.Map[result] = actualNotice;
return result;
}
// ...
}
Keep in mind that you only need to wrap the classes and parts of the public interface that you're going to use. The object will still behave the same internally, even if you don't wrap its entire public interface. This might mean you have to do less work, so think hard and try to wrap only what you need now, and what you know you're going to need in the future. Keep YAGNI in mind.
The programming style I have come to really like for problems like this is to write as much strongly-typed code as possible, and then hand off the logic from the dynamically-typed code to the strongly-typed code. So I would write your code like this:
//your code which gets types
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
//construct my helper object
var makeDelegateHelperType=typeof(MakeDelegateHelper<,>).MakeGenericType(clientType, noticeType);
var makeDelegateHelper=(MakeDelegateHelper)Activator.CreateInstance(makeDelegateHelperType);
//now I am in strongly-typed world again
var sendAction=makeDelegateHelper.MakeSendAction();
And this is the definition of the helper object, which is able to get away with fewer reflectiony calls.
public abstract class MakeDelegateHelper {
public abstract Action<object> MakeSendAction();
}
public class MakeDelegateHelper<TClient,TNotice> : MakeDelegateHelper where TClient : new() {
public override Action<object> MakeSendAction() {
var sendMethod = typeof(TClient).GetMethod("Send", new[] { typeof(TNotice) });
var client=new TClient();
var action=(Action<TNotice>)Delegate.CreateDelegate(typeof(Action<TNotice>), client, sendMethod);
return o => action((TNotice)o);
}
}
I've something along this lines:
public class Something
{
private IDictionary<object,Activity> fCases;
public IDictionary<object,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
public sealed class Something<T> : Something
{
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
}
Note: override is not accepted on this case
Due to heavy Reflection usage there are situations where I've to downcast from Something<T> to Something but, I guess because Cases property is hidden, I'm losing Cases data.
How can I circumvent this situation? I've tried to use where T:object but that isn't accepted also.
EDIT:
This is an example of why I need inheritance:
if (someVar is Something) {
if (someVar.GetType().IsGenericType)
{
// Construct AnotherObject<T> depending on the Something<T>'s generic argument
Type typeArg = someVar.GetType().GetGenericArguments()[0],
genericDefinition = typeof(AnotherObject<>),
typeToConstruct = genericDefinition.makeGenericType(typeArgs);
object newAnotherObject = Activator.CreateInstance(typeToConstruct);
// Pass Something 'Cases' property to AnotherObject<T>
constructedType.InvokeMember(
"Cases",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.SetProperty,
null,
newActivity,
new Object[] { someVar.Cases });
}
}
But, because 'Cases' is hidden, it will be always null. Without inheritance I would have to write a BIG if-then-else with all the possible generic arguments. And, believe me, I do really have to use someVar is Something and Reflection to construct all this objects. This is a big generic API being converted to other big generic API and so they should not known each other and the conversion should be as transparent as possible.
You won't be able to override it like that, and for good reason.
Imagine:
Something x = new Something<string>();
Button key = new Button();
x.Cases[key] = new Activity();
If your override worked, that would be trying to store a Button reference as a key in Dictionary<string, Activity>. That would be a Bad Thing.
Perhaps inheritance isn't actually appropriate in this case? If you could explain more about what you're trying to achieve, that would help. Perhaps you don't really need the dictionary as a property? Maybe just a method to fetch by key?
This is flat-out not going to work because the IDictionary<TKey, TValue> interface is invariant. An IDictionary<object, Activity> cannot be treated as an IDictionary<T, Activity>.
What you could do, rather than exposing an entire IDictionary<T, Activity> in your derived class, is simply delegate the calls you want to expose, like this:
public class Something
{
protected IDictionary<object, Activity> Cases { get; set; }
}
public sealed class Something<T> : Something
{
public Activity GetCase(T key)
{
return Cases[key];
}
public void AddCase(T key, Activity case)
{
Cases.Add(key, case);
}
// etc. etc.
}
Alternatively, you could also define your own contravariant interface, something like:
interface IKeyedCollection<in TKey, TValue>
{
TValue this[TKey key] { get; set; }
void Add(TKey key, TValue value);
}
For the above interface, an IKeyedCollection<object, Activity> could act as an IKeyedCollection<T, Activity> because every T is an object.
If you attempt to expose incompatible types at the different levels you're going to keep running into problems because at the end of the day you'll end up having to maintain 2 separate objects (or 1 custom object with 2 interfaces it can't completely satisfy).
These types are incompatible because there are values which can be added to IDictionary<object, Activity> which cannot be added to every instantiation of IDictionary<T, Activity>. Imagine for instance T is instatiated as string and the developer uses a int key elsewhere via Something. This creates a real problem for Something<string> implementations.
The way I would approach this is to change the base type Something to not expose a concrete type but instead to expose the relevant APIs.
public abstract class Something {
public abstract IEnumerable<KeyValuePair> GetElements();
public abstract bool TryGetValue(object key, out Activity value);
}
This gives Something<T> the flexbility it needs to properly sub-class Something and be very expressive about the types it wants to expose
public sealed class Something<T> : Something {
private IDictionary<T,Activity> fCases;
public override IDictionary<T,Activity> Cases
{
get { return fCases; }
set { fCases = value; }
}
public override IEnumerable<KeyValuPair<object, Activity>> GetElements() {
foreach (var cur in fCases) {
yield return new KeyValuePair<object, Activity>(cur.Key, cur.Value);
}
}
public override bool TryGetValue(object key, out Activity activity) {
try {
T typedKey = (T)key;
return fCases.TryGetValue(typedKey, out activity);
} catch (InvalidCastException) {
activity = null;
return false;
}
}
}
}
During heavy reflection usage I also had the need to 'upcast' from generic types. I knew certain calls would be compatible, but I didn't know the types at compile time. If you look at it this way, it is not really 'upcasting' a generic type, but rather, allowing to use generics during reflection by generating the correct downcasts.
To this end I created a helper method to create delegates along the lines of Delegate.CreateDelegate, but allowing to create a less generic delegate. Downcasts are generated where necessary. I explain it in detail on my blog.
MethodInfo methodToCall = typeof( string ).GetMethod( "Compare" );
Func<object, object, int> unknownArgument
= DelegateHelper.CreateDowncastingDelegate<Func<object, object, int>>(
null, methodToCall );
unknownArgument( "test", "test" ); // Will return 0.
unknownArgument( "test", 1 ); // Will compile, but throw InvalidCastException.
A bit later I had a need to create entire less generic wrapper classes for generic classes, so that all method calls would immediately become available as less generic calls during reflection. This might or might not be useful in your scenario as well. For this purpose I created a (not as thoroughly tested) method which allows to generate this wrapper class at runtime using emit. It is available in my open source library. I haven't written about this yet, so when interested you'll just have to try it out (and possibly see it fail since it's still quite new).
Here's the code:
public interface IValidator<T>
{
bool IsValid(T obj);
}
public class OrderValidator: IValidator<Order>
{
// ...
}
public class BaseEntity
{
}
public class Order: BaseEntity
{
}
The problem is that I can't do:
var validator = new OrderValidator();
// this line throws because type can't be converted
var baseValidator = (IValidator<BaseEntity>)validator;
// all this is because I need a list with IValidator<Order>, IValidator<BaseOrder>, etc.
IList<IValidator<BaseEntity>> allValidators = ...
How do I get and store a list of all implementations of IValidator<T> for base T - say, BaseEntity? Currently I do non-generic IValidator that accepts "object obj" but it is not good and not type-safe.
The funny stuff is that C# allows to compile:
var test = (IValidator<BaseEntity>)new OrderValidator();
but fails at runtime with
Unable to cast object of type 'OrderValidator' to type 'IValidator`1[Orders.Core.BaseEntity]'
This is the same exception that Windsor gives me (I tried both Windsor and manual types lookup, this issue is really not related to this, only to the interfaces casting).
Thanks to Heinzi, I see now why I can't cast - because IValidator for Order expects Order as generic type. But how do I return a list of IValidator for different types? The reason is that the BaseEntity takes its real type and gathers all validators - for all types from GetType() to the object. I'd really like to have a generic GetValidators() and then operate on it.
Maybe it helps you if I explain why this cast is forbidden: Assume that you have the following function
void myFunc(IValidator<BaseEntity> myValidator) {
myValidator.IsValid(new BaseEntity());
}
This code would compile correctly. Nevertheless, if you passed an OrderValidator to this function, you would get a run-time exception, because OrderValidator.IsValid expects an Order, not a BaseEntity. Type safety would no longer be maintained if your cast were allowed.
EDIT: C# 4 allows for generic co- and contravariance, but this would not help in your case, since you use T as an input parameter. Thus, only casting to an IValidator<SomeSubtypeOfOrder> could be done in a type-safe way.
So, to be clear, you cannot cast OrderValidator to IValidator<BaseEntity> because your OrderValidator can only validate orders, not all kinds of BaseEntities. This, however, is what would be expected of an IValidator<BaseEntity>.
The cast doesn't work because IValidator<Order> and IValidator<BaseEntity> are totally unrelated types. IValidator<Order> is not a subtype of IValidator<BaseEntity>, so they can't be cast.
C# does support multiple interface inheritance, so the simplest way to handle this is to make your order validator inherit from an interface for both validator types, that way it you will be able to cast it to either interface as required. Obviously this means you will have to implement both interfaces and specify how to handle the base when a BaseEntity provided doesn't match the type the validator is for.
Something like this:
public class OrderValidator : IValidator<Order>, IValidator<BaseEntity>
{
public bool IsValid(Order obj)
{
// do validation
// ...
return true;
}
public bool IsValid(BaseEntity obj)
{
Order orderToValidate = obj as Order;
if (orderToValidate != null)
{
return IsValid(orderToValidate);
}
else
{
// Eiter do this:
throw new InvalidOperationException("This is an order validator so you can't validate objects that aren't orders");
// Or this:
return false;
// Depending on what it is you are trying to achive.
}
}
}
This relates to what Heinzi says about not being able to cast because an IValidator<BaseEntity> needs to be able to validate BaseEntities, which your current OrderValidator can't do. By adding this multiple interface you explicitly define the behaviour for validating BaseEntities (by either explicitly ignoring it or causing an exception) so the cast becomes possible.
While this won't answer you directly, I'd recommend taking a look at the source code for StructureMap, they do alot of work with open generic types. Actually might even want to use StructureMap to handle caching of your validators, this is exactly what i do.
ForRequestedType(typeof (ValidationBase<>)).CacheBy(InstanceScope.Singleton);
Scan(assemblies =>
{
assemblies.TheCallingAssembly();
assemblies.AddAllTypesOf(typeof(IValidation<>));
});
Then I have a factory class to do the actual validation
public static class ValidationFactory
{
public static Result Validate<T>(T obj)
{
try
{
var validator = ObjectFactory.GetInstance<IValidator<T>>();
return validator.Validate(obj);
}
catch (Exception ex)
{
...
}
}
}
Edit: I wrote a big blog post on generic validation using IoC, if you take a look at it since you said you already use Spring, I bet you could adapt my work to solve your problem: Creating a generic validation framework