First, excuse the rather funny name of my question. I'm no native speaker and it took me 10 minutes to express my thoughts in these few characters.
What I'm trying to do is to create a dictionary in C# that allows the value to be either an int, a string or a bool. What first had come to my mind was using generics, but as far as I know, I can only define one type as possible value-type, not "be one of those". Using object would also be possible, but boxing seems to be quite a performance-killer.
Is there any way to do this?
Here's a sample of what has come to my mind:
Dictionary<string, (string, int, bool)> foo = new Dictionary<string, (string, int, bool)>();
foo.Add("key1", "Hello, World!"); //Correct - Value is a string
foo.Add("key2", 37); //Correct - Value is an int
foo.Add("key3", true); //Correct - Value is a boolean
foo.Add("key4", new Foobar()); //Compiler error - Value is a Foobar
My ultimate goal is to provide a library for other developers. This feature should enable them to define "variables" during runtime and give them a type.
Edit://Firefox' about:config page has something very close to what I want to achieve
Why not create a fresh new class which implements the IDictionary and uses a Dictionary as a private variable.
Then, in the add methods, you can provide your own logic and fail accordingly
Sample code
public class MyDic : IDictionary<object, object>
{
private Dictionary<object, object> privateDic= new Dictionary<object,object>();
public void Add(object key, object value)
{
if (value.GetType() == typeof(string))
throw new ArgumentException();
privateDic.Add(key, value);
}
//Rest of the interface follows
}
I would suggest to:
Create a base type for your dictionary values e.g. MyDictionaryBaseType
Extend this basic type for each dictionary value type your have e.g. StringDictionryType : MyDictionaryBaseType, IntegerDictionryType : MyDictionaryBaseType...etc.
Create a generic dictionary type with MyDictionaryBaseType and limit the type to extend this base type.
This way you limit your dictionry to three specifed types
You can put the values into wrapper classs like this:
class Value
{
}
class TypedValue<T> : Value
{
public T Val;
}
class IntValue : TypedValue<int>
{
}
class StringValue : TypedValue<string>
{
}
class BoolValue : TypedValue<bool>
{
}
Dictionary<string,Value> foo;
foo.Add("key1", new StringValue{Val="Hello World!"});
Another possibility would be to use a Dictionary and do a runtime check for right or wrong types added. I don't think there is a solution without involving boxing.
What you are trying to accomplish isn't type-safe as it stands. For example, let's say you have such a dictionary:
var foo = new Dictionary<string, (string, int, bool)>();
var x = foo["key1"];
// What type is x? How could the compiler know?
One idea would be to devise a container class which can hold one-of either string, int, or bool.
public class StringIntBool {
private bool _isSet;
private bool _isString;
public bool IsString {
get { return _isString; }
}
// ...
private string _innerString;
public string InnerString {
get {
return _innerString;
}
set {
if (_isSet) {
throw new Exception("StringIntBool is already set");
}
_isSet = true;
_isString = true;
_innerString = value;
}
}
// etc...
}
This is quite ugly, and doesn't really give many benefits.
As an alternative, you could actually store all three values as objects, and then use a technique / library like Functional C# to perform pattern-matching, like many functional languages can.
object x = "str";
int res = x.Match()
.With<string>(s => s == "str" ? 10 : 20)
.With<int>(i => i)
.With<bool>(b => b ? 50 : 60)
.Return<int>();
This pattern of programming is actually pretty common in certain functional language. For example, in SML, you can define a datatype, and then pattern-match it as needed.
(* StringIntBool *)
datatype sib = SibString of string | SibInt of int | SibBool of bool
val x = (* some instance of sib *)
val y = case x of
SibString s => if s = "hello" then 50 else -50
| SibInt i => i
| SibBool b => if b then 10 else 20
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>>();
To be clear, I want the behavior of a pointer-to-a-pointer, and the purpose of this question is to generate clean, readable code.
I have some code that contains conditions checking the result of multiple Dictionary.TryGetValue calls. It would be cleaner if it could retrieve all of the required objects with a single call, so I wanted to write an extension that will allow me to do the following:
Dictionary<string, string> myDictionary; // Initialized somewhere
string x, y, z;
bool foundAllEntries = myDictionary.TryGetValues({"xvalue", out x}, {"yvalue", out y},
{"zvalue", out z});
if (foundAllEntries)
; // Do something with x, y, and z
However, I can't figure out a way to pass the extension method references to the objects that will hold the output. This seems like something that should be very basic.
How can I store a reference to a local reference in an object?
Please note that this question is not asking for alternative approaches to implementing the TryGetValues function. There are many ways I can make this 'work,' but none generate code as clean as the approach I'm trying to take.
This seems like something that should be very basic.
Not only it isn't basic, it's outright impossible: there is no way to decorate a data type with ref or out - these modifiers are applicable exclusively to formal method parameters. In other words, there is no such thing as a "reference variable" or an "output variable"; there are only "reference parameters" and "output parameters" in the language.
Moreover, you cannot pass output or by reference parameters as part of a variable-length argument list (i.e. the params portion) so that approach wouldn't work either.
There are many ways I can make this 'work,' but none generate code as clean as the approach I'm trying to take.
Curiously, the above does not mean that you cannot implement the scheme that you are trying to implement, leaving the code nearly as clean as your original one if you apply the Proxy Design Pattern. The trick is to chain method calls, and provide an implicit conversion operator for the result, like this:
class MyMap {
internal IDictionary<string,string> dict = ...
public ItemGetterResult TryGetValues {
get {
return new ItemGetterResult(this, true);
}
}
}
class ItemGetterResult {
private readonly MyMap map;
private bool IsSuccessful {get;set;}
internal ItemGetterResult(MyMap theMap, bool successFlag) {
map = theMap;
IsSuccessful = successFlag;
}
public static implicit operator bool(ItemGetterResult r) {
return r.IsSuccessful;
}
public ItemGetterResult Get(string key, out string val) {
return new ItemGetterResult(
map
, this.IsSuccessful && map.dict.TryGetValue(key, out val)
);
}
}
Now the call looks like this:
bool foundAllEntries = myDictionary.TryGetValues
.Get("xvalue", out x)
.Get("yvalue", out y)
.Get("zvalue", out z);
You can create a mutable Reference type:
public class Reference<T>
{
public T Value;
}
/* declaration */
bool TryGetValues(
this Dictionary<K,V> dict,
params Tuple<K, Reference<V>>[] requests)
/* call site */
var x = new Reference<string>();
var y = new Reference<string>();
var z = new Reference<string>();
bool foundAllEntries = myDictionary.TryGetValues(
Tuple.Create("xvalue", x),
Tuple.Create("yvalue", y),
Tuple.Create("zvalue", z));
I have a method that uses an IList<T> as a parameter. I need to check what the type of that T object is and do something based on it. I was trying to use the T value, but the compiler does not not allow it. My solution is the following:
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
if (clause[0] is int || clause[0] is decimal)
{
//do something
}
else if (clause[0] is String)
{
//do something else
}
else if (...) //etc for all the types
else
{
throw new ApplicationException("Invalid type");
}
}
}
There has to be a better way to do this. Is there some way I can check the type of T that is passed in and then use a switch statement?
You could use overloads:
public static string BuildClause(List<string> l){...}
public static string BuildClause(List<int> l){...}
public static string BuildClause<T>(List<T> l){...}
Or you could inspect the type of the generic parameter:
Type listType = typeof(T);
if(listType == typeof(int)){...}
You can use typeof(T).
private static string BuildClause<T>(IList<T> clause)
{
Type itemType = typeof(T);
if(itemType == typeof(int) || itemType == typeof(decimal))
...
}
And, because C# has evolved, you can (now) use pattern matching.
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
switch (clause[0])
{
case int x: // do something with x, which is an int here...
case decimal x: // do something with x, which is a decimal here...
case string x: // do something with x, which is a string here...
...
default: throw new Exception("Invalid type");
}
}
}
And again with switch expressions in C# 8.0, the syntax gets even more succinct.
private static string BuildClause<T>(IList<T> clause)
{
if (clause.Count > 0)
{
return clause[0] switch
{
int x => "some string related to this int",
decimal x => "some string related to this decimal",
string x => x,
...,
_ => throw new Exception("Invalid type")
}
}
}
I hope you find this helpful:
typeof(IList<T>).IsGenericType == true
typeof(IList<T>).GetGenericTypeDefinition() == typeof(IList<>)
typeof(IList<int>).GetGenericArguments()[0] == typeof(int)
https://dotnetfiddle.net/5qUZnt
By default know there is not a great way. Awhile back I got frustrated with this and wrote a little utility class that helped out a bit and made the syntax a bit cleaner. Essentially it turns the code into
TypeSwitcher.Do(clause[0],
TypeSwitch.Case<int>(x => ...), // x is an int
TypeSwitch.Case<decimal>(d => ...), // d is a decimal
TypeSwitch.Case<string>(s => ...)); // s is a string
Full blog post and details on the implementation are available here
http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx
The typeof operator...
typeof(T)
... won't work with the c# switch statement. But how about this? The following post contains a static class...
Is there a better alternative than this to 'switch on type'?
...that will let you write code like this:
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));
There is no way to use the switch statement for what you want it to do. The switch statement must be supplied with integral types, which does not include complex types such as a "Type" object, or any other object type for that matter.
For everyone that says checking types and doing something based on the type is not a great idea for generics I sort of agree but I think there could be some circumstances where this perfectly makes sense.
For example if you have a class that say is implemented like so (Note: I am not showing everything that this code does for simplicity and have simply cut and pasted into here so it may not build or work as intended like the entire code does but it gets the point across. Also, Unit is an enum):
public class FoodCount<TValue> : BaseFoodCount
{
public TValue Value { get; set; }
public override string ToString()
{
if (Value is decimal)
{
// Code not cleaned up yet
// Some code and values defined in base class
mstrValue = Value.ToString();
decimal mdecValue;
decimal.TryParse(mstrValue, out mdecValue);
mstrValue = decimal.Round(mdecValue).ToString();
mstrValue = mstrValue + mstrUnitOfMeasurement;
return mstrValue;
}
else
{
// Simply return a string
string str = Value.ToString() + mstrUnitOfMeasurement;
return str;
}
}
}
...
public class SaturatedFat : FoodCountWithDailyValue<decimal>
{
public SaturatedFat()
{
mUnit = Unit.g;
}
}
public class Fiber : FoodCount<int>
{
public Fiber()
{
mUnit = Unit.g;
}
}
public void DoSomething()
{
nutritionFields.SaturatedFat oSatFat = new nutritionFields.SaturatedFat();
string mstrValueToDisplayPreFormatted= oSatFat.ToString();
}
So in summary, I think there are valid reasons why you might want to check to see what type the generic is, in order to do something special.
Your construction completely defeats the purpose of a generic method. It's ugly on purpose because there must be a better way to achieve what you're trying to accomplish, although you haven't given us quite enough information to figure out what that is.
You can do typeOf(T), but I would double check your method and make sure your not violating single responsability here. This would be a code smell, and that's not to say it shouldn't be done but that you should be cautious.
The point of generics is being able to build type-agnostic algorthims were you don't care what the type is or as long as it fits within a certain set of criteria. Your implementation isn't very generic.
How about this :
// Checks to see if the value passed is valid.
if (!TypeDescriptor.GetConverter(typeof(T)).IsValid(value))
{
throw new ArgumentException();
}
My two cents:
In case you happen to have a generic method that returns a generic value but doesn't have generic parameters, you can use default(T) + (T)(object) cast, together with C# 8 pattern matching/type checks (as indicated in the other recent answers).
Example:
private static T Parse<T>(string str)
{
return default(T) switch
{
short => (T)(object)short.Parse(str),
ushort => (T)(object)ushort.Parse(str),
int => (T)(object)int.Parse(str),
uint => (T)(object)uint.Parse(str),
long => (T)(object)long.Parse(str),
ulong => (T)(object)ulong.Parse(str),
_ => throw new ArgumentException()
};
}
I have method that transforms some input value by the user passing it a Func delegate wich returns the new value (very over simplified for what I am trying to achieve)
public L Coerce<L>(string value, Func<string, L> coercer)
{
return coercer(value);
}
Coerce<int>("123", v => int.Parse(v));
This is fine however I also want to be able to write methods that override the behaviour for a specific type eg...
public int Coerce<int>(string value)
{
return Coerce<int>(value, v => int.Parse(v));
}
So basically calling
Coerce<int>("123"); // equivalent Coerce<int>("123", v => int.Parse(v));
will save me having to re-write the int.Parse for every Coerce. Of course this should then extend to handle
public decimal Coerce<decimal>(string value)
{
return Coerce<decimal>(value, v => int.Parse(v));
}
Etc etc.
Can this be done neatly?
James
Well, if you really don't want to do
Convert.ToInt32(value)
Then this will do what you are asking:
public T Coerce<T>(string value) where T : IConvertible
{
return (T)(((IConvertible)value).ToType(typeof(T),
CultureInfo.InvariantCulture));
}
Hence:
int x = Coerce<int>("123");
or
byte b = Coerce<byte>("123");
This will give you a compile-time error if you try to coerce to a non-convertible type, for example:
var x = Coerce<MyClass>("123"); //compile-time error
In which case you force the caller to use your Coerce(string value, Func<string,T> coercer) overload.
You could use a non-generic version:
public int CoerceInt32(string value)
{
return Coerce(value, int.Parse);
}
What is the purpose of this method?
Why do you want to write this:
int x = Coerce<int>("123", v => int.Parse(v));
instead of just this:
int x = int.Parse("123");
However, to answer your question, no, not "neatly". .Parse is a static method on the int and decimal types, and thus not available through your generic type.
The best you can hope for is to either write one overload per type you want to handle, or to write reflection code inside your method to figure out which static method to call.
And thus you get into a problem when you write this:
MyMagicType x = Coerce<MyMagicType>("123");
what then? Will you assume that MyMagicType has a .Parse method?
I'm afraid C# doesnt have template overriding like in C++. I came across a similar situation, and the way I had to work around it is to check the type at runtime:
public void DoStuff<T>(Dictionary<object, T> arg) {
// ....
if (typeof(T) == typeof(ClassA)) {
DoStuff((Dictionary<object, ClassA>)arg);
}
else (typeof(T) == typeof(ClassB)) {
DoStuff((Dictionary<object, ClassB>)arg);
}
else {
throw new ArgumentException("T must be ClassA or ClassB");
}
}
I am wondering what it would take to make something like this work:
using System;
class Program
{
static void Main()
{
var f = new IFoo {
Foo = "foo",
Print = () => Console.WriteLine(Foo)
};
}
}
interface IFoo
{
String Foo { get; set; }
void Print();
}
The anonymous type created would look something like this:
internal sealed class <>f__AnonymousType0<<Foo>j__TPar> : IFoo
{
readonly <Foo>j__TPar <Foo>i__Field;
public <>f__AnonymousType0(<Foo>j__TPar Foo)
{
this.<Foo>i__Field = Foo;
}
public <Foo>j__TPar Foo
{
get { return this.<Foo>i__Field; }
}
public void Print()
{
Console.WriteLine(this.Foo);
}
}
Is there any reason that the compiler would be unable to do something like this? Even for non-void methods or methods that take parameters the compiler should be able to infer the types from the interface declaration.
Disclaimer: While I do realize that this is not currently possible and it would make more sense to simply create a concrete class in this instance I am more interested in the theoretical aspects of this.
There would be a few issues with overloaded members, indexers, and explicit interface implementations.
However, you could probably define the syntax in a way that allows you to resolve those problems.
Interestingly, you can get pretty close to what you want with C# 3.0 by writing a library. Basically, you could do this:
Create<IFoo>
(
new
{
Foo = "foo",
Print = (Action)(() => Console.WriteLine(Foo))
}
);
Which is pretty close to what you want. The primary differences are a call to "Create" instead of the "new" keyword and the fact that you need to specify a delegate type.
The declaration of "Create" would look like this:
T Create<T> (object o)
{
//...
}
It would then use Reflection.Emit to generate an interface implementation dynamically at runtime.
This syntax, however, does have problems with explicit interface implementations and overloaded members, that you couldn't resolve without changing the compiler.
An alternative would be to use a collection initializer rather than an anonymous type. That would look like this:
Create
{
new Members<IFoo>
{
{"Print", ((IFoo #this)=>Console.WriteLine(Foo))},
{"Foo", "foo"}
}
}
That would enable you to:
Handle explicit interface implementation by specifying something like "IEnumerable.Current" for the string parameter.
Define Members.Add so that you don't need to specify the delegate type in the initializer.
You would need to do a few things to implement this:
Writer a small parser for C# type names. This only requires ".", "[]", "<>",ID, and the primitive type names, so you could probably do that in a few hours
Implement a cache so that you only generate a single class for each unique interface
Implement the Reflection.Emit code gen. This would probably take about 2 days at the most.
It requires c# 4, but the opensource framework impromptu interface can fake this out of the box using DLR proxies internally. The performance is good although not as good as if the change you proposed existed.
using ImpromptuInterface.Dynamic;
...
var f = ImpromptuGet.Create<IFoo>(new{
Foo = "foo",
Print = ReturnVoid.Arguments(() => Console.WriteLine(Foo))
});
An anonymous type can't be made to do anything except to have read-only properties.
Quoting the C# Programming Guide (Anonymous Types):
"Anonymous types are class types that
consist of one or more public
read-only properties. No other kinds
of class members such as methods or
events are allowed. An anonymous type
cannot be cast to any interface or
type except for object."
As long as we're putting out an interface wish list, I'd really like to be able to tell the compiler that a class implements an interface outside the class definition- even in a separate assembly.
For example, let's say I'm working on a program to extract files from different archive formats. I want to be able to pull in existing implementations from different libraries — say, SharpZipLib and a commercial PGP implementation — and consume both libraries using the same code without creating new classes. Then I could use types from either source in generic constraints, for example.
Another use would be telling the compiler that System.Xml.Serialization.XmlSerializer implements the System.Runtime.Serialization.IFormatter interface (it already does, but the compiler doesn't know it).
This could be used to implement your request as well, just not automatically. You'd still have to explicitly tell the compiler about it. Not sure how the syntax would look, because you'd still have to manually map methods and properties somewhere, which means a lot of verbiage. Maybe something similar to extension methods.
You could have something like anonymous classes in Java:
using System;
class Program {
static void Main() {
var f = new IFoo() {
public String Foo { get { return "foo"; } }
public void Print() { Console.WriteLine(Foo); }
};
}
}
interface IFoo {
String Foo { get; set; }
void Print();
}
Wouldn't this be cool. Inline anonymous class:
List<Student>.Distinct(new IEqualityComparer<Student>()
{
public override bool Equals(Student x, Student y)
{
return x.Id == y.Id;
}
public override int GetHashCode(Student obj)
{
return obj.Id.GetHashCode();
}
})
I'm going to dump this here. I wrote it a while ago but IIRC it works OK.
First a helper function to take a MethodInfo and return a Type of a matching Func or Action. You need a branch for each number of parameters, unfortunately, and I apparently stopped at three.
static Type GenerateFuncOrAction(MethodInfo method)
{
var typeParams = method.GetParameters().Select(p => p.ParameterType).ToArray();
if (method.ReturnType == typeof(void))
{
if (typeParams.Length == 0)
{
return typeof(Action);
}
else if (typeParams.Length == 1)
{
return typeof(Action<>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 2)
{
return typeof(Action<,>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 3)
{
return typeof(Action<,,>).MakeGenericType(typeParams);
}
throw new ArgumentException("Only written up to 3 type parameters");
}
else
{
if (typeParams.Length == 0)
{
return typeof(Func<>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 1)
{
return typeof(Func<,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 2)
{
return typeof(Func<,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 3)
{
return typeof(Func<,,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
throw new ArgumentException("Only written up to 3 type parameters");
}
}
And now the method that takes an interface as a generic parameter and returns a Type that implements the interface and has a constructor (needs to be called via Activator.CreateInstance) taking a Func or Action for each method/ getter/setter. You need to know the right order to put them in the constructor, though. Alternatively (commented-out code) it can generate a DLL which you can then reference and use the type directly.
static Type GenerateInterfaceImplementation<TInterface>()
{
var interfaceType = typeof(TInterface);
var funcTypes = interfaceType.GetMethods().Select(GenerateFuncOrAction).ToArray();
AssemblyName aName =
new AssemblyName("Dynamic" + interfaceType.Name + "WrapperAssembly");
var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
aName,
AssemblyBuilderAccess.Run/*AndSave*/); // to get a DLL
var modBuilder = assBuilder.DefineDynamicModule(aName.Name/*, aName.Name + ".dll"*/); // to get a DLL
TypeBuilder typeBuilder = modBuilder.DefineType(
"Dynamic" + interfaceType.Name + "Wrapper",
TypeAttributes.Public);
// Define a constructor taking the same parameters as this method.
var ctrBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.Standard,
funcTypes);
// Start building the constructor.
var ctrGenerator = ctrBuilder.GetILGenerator();
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(
OpCodes.Call,
typeof(object).GetConstructor(Type.EmptyTypes));
// For each interface method, we add a field to hold the supplied
// delegate, code to store it in the constructor, and an
// implementation that calls the delegate.
byte methodIndex = 0;
foreach (var interfaceMethod in interfaceType.GetMethods())
{
ctrBuilder.DefineParameter(
methodIndex + 1,
ParameterAttributes.None,
"del_" + interfaceMethod.Name);
var delegateField = typeBuilder.DefineField(
"del_" + interfaceMethod.Name,
funcTypes[methodIndex],
FieldAttributes.Private);
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(OpCodes.Ldarg_S, methodIndex + 1);
ctrGenerator.Emit(OpCodes.Stfld, delegateField);
var metBuilder = typeBuilder.DefineMethod(
interfaceMethod.Name,
MethodAttributes.Public | MethodAttributes.Virtual |
MethodAttributes.Final | MethodAttributes.HideBySig |
MethodAttributes.NewSlot,
interfaceMethod.ReturnType,
interfaceMethod.GetParameters()
.Select(p => p.ParameterType).ToArray());
var metGenerator = metBuilder.GetILGenerator();
metGenerator.Emit(OpCodes.Ldarg_0);
metGenerator.Emit(OpCodes.Ldfld, delegateField);
// Generate code to load each parameter.
byte paramIndex = 1;
foreach (var param in interfaceMethod.GetParameters())
{
metGenerator.Emit(OpCodes.Ldarg_S, paramIndex);
paramIndex++;
}
metGenerator.EmitCall(
OpCodes.Callvirt,
funcTypes[methodIndex].GetMethod("Invoke"),
null);
metGenerator.Emit(OpCodes.Ret);
methodIndex++;
}
ctrGenerator.Emit(OpCodes.Ret);
// Add interface implementation and finish creating.
typeBuilder.AddInterfaceImplementation(interfaceType);
var wrapperType = typeBuilder.CreateType();
//assBuilder.Save(aName.Name + ".dll"); // to get a DLL
return wrapperType;
}
You can use this as e.g.
public interface ITest
{
void M1();
string M2(int m2, string n2);
string prop { get; set; }
event test BoopBooped;
}
Type it = GenerateInterfaceImplementation<ITest>();
ITest instance = (ITest)Activator.CreateInstance(it,
new Action(() => {Console.WriteLine("M1 called"); return;}),
new Func<int, string, string>((i, s) => "M2 gives " + s + i.ToString()),
new Func<String>(() => "prop value"),
new Action<string>(s => {Console.WriteLine("prop set to " + s);}),
new Action<test>(eh => {Console.WriteLine(eh("handler added"));}),
new Action<test>(eh => {Console.WriteLine(eh("handler removed"));}));
// or with the generated DLL
ITest instance = new DynamicITestWrapper(
// parameters as before but you can see the signature
);
Interesting idea, I'd be a little concerned that even if it could be done it might get confusing. E.g. when defining a property with non-trivial setters and getters, or how to disambiguate Foo if the the declaring type also contained a property called Foo.
I wonder if this would be easier in a more dynamic language, or even with the dynamic type and DLR in C# 4.0?
Perhaps today in C# some of the intent could be achieved with lambdas:
void Main() {
var foo = new Foo();
foo.Bar = "bar";
foo.Print = () => Console.WriteLine(foo.Bar);
foo.Print();
}
class Foo : IFoo {
public String Bar { get; set; }
public Action Print {get;set;}
}
This wouldn't be possible currently.
What would be the difference between this and simply making IFoo a concrete class instead? Seems like that might be the better option.
What it would take? A new compiler and tons of checks to ensure they didn't break the other features. Personally, I think it'd just be easier to require developers to just create a concrete version of their class.
I have used in Java the Amonimous Class through the "new IFoo(){...}" sintax and it's practical and easy when you have to quick implement a simple interface.
As a sample it would be nice to implement IDisposable this way on a legacy object used just one time instead of deriving a new class to implement it.