I am trying to construct some objects in a reasonably generic way. Some of the objects have constructor params, others don't.
What I am trying to achieve is to return some kind of builder function to which I can supply the constructor param if required.
I know I could have optional params passed down, but in my real scenario, there are several layers and I'm loathed to add optional params down the hierarchy.
I'm not too up on partial application/currying, but could I use that here and if so, how?
Here's a bit of sample code - which won't work - to try and explain a bit more what I'm after.
public void Main()
{
dynamic buildClass = ClassBuilder<BaseClass>(true);
// ideally I'd like to be able to supply the constructor data
// here
var theClass = buildClass(???)
}
public Func<???, TClass> ClassBuilder<TClass>(bool flag) where TClass : BaseClass
{
// obviously this won't work since the delegates have different
// signatures
if (flag) return () => GetClassA();
return (x) => GetClassB(x);
}
public object GetClassA()
{
return new ClassA();
}
public object GetClassB(string param)
{
return new ClassB(param);
}
public class BaseClass {}
public class ClassA : BaseClass {}
public class ClassB : BaseClass
{
private string _param;
public ClassB(string param)
{
_param = param;
}
}
Many thx
S
To elaborate #Sylwekqaz you could have something like below, and not restrict yourself for type of BaseClass.
public static class Builder
{
public static T Build<T>(params object[] args) where T : class
{
var info = typeof(T).GetConstructor(args.Select(arg => arg.GetType()).ToArray());
if (info == null)
throw new ArgumentException(#"Can't get constructor :(", "args");
return (T)info.Invoke(args.ToArray());
}
}
And then you can call your builder as
var a = Builder.Build<ClassA>();
var b = Builder.Build<ClassB>(); // need parameterless ctor in ClassB
var c = Builder.Build<ClassB>("param");
You must use code reflection to detect constructor/method with you parameters and invoke it.
Type type = typeof(YourClass);
ConstructorInfo ctor = type.GetConstructor(new[] { typeof(string) });
object instance = ctor.Invoke(new object[] { 10 });
~source: Using C# reflection to call a constructor
alternatively you have a class MethodInfo if you must use methods GetClassX
More info
https://msdn.microsoft.com/en-us/library/system.type.getconstructor%28v=vs.110%29.aspx
https://msdn.microsoft.com/en-us/library/system.reflection.constructorinfo.invoke%28v=vs.110%29.aspx
I don't entirely follow your code example, but you ask about partial-application and currying...
The best way I've found is to just create N functions that take from 1-N generic parameters, then let the compiler pick the one you want. If you take a look at my language-ext project I have two functions, one called curry and one called par for currying and partial application:
Currying source
Partial application source
To partially apply, do this:
// Example function
int AddFour(int a,int b,int c, int d)
{
return a + b + c + d;
}
// This returns a Func<int,int,int> with the first two arguments 10 & 5 auto-provided
var tenfive = par(AddFour, 10, 5);
// res = 10 + 5 + 1 + 2
var res = tenfive(1,2);
To curry, do this:
// Example function
int AddFour(int a,int b,int c, int d)
{
return a + b + c + d;
}
// Returns Func<int,Func<int,Func<int,Func<int,int>>>>
var f = curry(AddFour);
// res = 10 + 5 + 1 + 2
var res = f(10)(5)(1)(2);
Related
Is there a way in C# to perform a user defined conversion for generic types ?
for example:
class Stack<T>
{
private T x; //should be an array but doesn't matter for this example
public Stack(T input)
{
x = input;
}
public Stack<Q> Convert<Q>(Stack<T> inputStack)
{
//what would go here ? The call is below.
}
}
//main code
Stack<int> stack = new Stack<int>(2);
Stack<long> longstack = stack.Convert<long>(stack);
I would imagine that the compiler can deduce that Q is long and T is int in the Convert function, but it doesn't seem to work.
No, because class-level generic type parameters can't be auto-infered from usage.
I would imagine that the compiler can deduce that Q is long and T is
int in the Convert function, but it doesn't seem to work.
Maybe, but at the end of the day, a generic type parameter doesn't belong to constructor. That is, you provide a generic argument to the type based on what constructor parameter/argument? What happens if there're more than a constructor parameter?
public class A<T>
{
// Which one should be used to auto-infer T from usage?
// Maybe the integer? Or the bool? Or just the string...?
// Every choice seems a joke, because it would be absolutely
// arbitrary and unpredictable...
public A(int x, string y, bool z)
{
}
}
Now take your sample code as example. It has the same issue: what argument should be used from your Convert static method to infer generic type argument from usage? What happens if Convert has more than an argument...?
Here is extension method for standart Stack class (you can rewrite it a little and use like instance method in your own Stack class):
public static class MyStackExtensions
{
public static Stack<TDest> Convert<TSrc, TDest>(
this Stack<TSrc> stack,
Func<TSrc, TDest> converter = null)
{
if (stack == null)
throw new ArgumentNullException("stack");
var items = converter == null
? stack.Select(i => (TDest) System.Convert.ChangeType(i, typeof (TDest)))
: stack.Select(converter);
return new Stack<TDest>(items.Reverse());
}
}
Convert stack from int to long using convert function - no type params needed :-)
var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert(i => (long)i);
Or using standart conversion:
var intStack = new Stack<int>(new[] { 1, 2, 3 });
var longStack = intStack.Convert<int, long>();
I'm using Type.GetConstructor(Type.EmptyTypes) to get the default constructor for a class. It works if the class has a default constructor with no parameters (class A). But it doesn't work if a class has a constructor with all parameters optional (class B). Program doesn't know what the optional parameters are because it only needs the default constructor. What can statements can I use to make it work for both cases? Thanks, appreciate any help!
public class A
{
public A() {}
}
public class B
{
public B(int i = 0, string str = "") {}
}
Say I have the following class:
public class SomeClass
{
public SomeClass()
{
}
public SomeClass(int x)
{
}
public SomeClass(int x = 0, int y = 0)
{
}
}
Basically, you're asking for a query that will find the constructors that match constructor 1 and 3 above? If so, use this:
var constuctors = typeof(SomeClass).GetConstructors()
.Where(x => x.GetParameters().Count() == 0
|| x.GetParameters().Count(param => param.GetCustomAttributes(typeof(OptionalAttribute), false).Count() > 0) == x.GetParameters().Count());
Incredibly nasty query, but it gets the job done returning only 1 and 3 above.
The problem is that the C# compiler produces this:
public class B
{
// Methods
public B([Optional, DefaultParameterValue(0)] int i, [Optional, DefaultParameterValue("")] string str)
{
}
}
Something like below should work:
public static class TypeHelper {
public static ConstructorInfo GetDefaultConstructor<TType>() {
var type = typeof(TType);
return type.GetDefaultConstructor();
}
public static ConstructorInfo GetDefaultConstructor(this Type type) {
if(type == null) throw new ArgumentNullException("type");
var constructor = type.GetConstructor(Type.EmptyTypes);
if(constructor == null) {
var ctors =
from ctor in type.GetConstructors()
let prms = ctor.GetParameters()
where prms.All(p=>p.IsOptional)
orderby prms.Length
select ctor;
constructor = ctors.FirstOrDefault();
}
return constructor;
}
}
The problem is that optional parameters are nothing more than a compile time concept. You'll need to specify the constructor completely.
var ci = typeof(B).GetConstructor(new [] { typeof(int), typeof(string) });
You can write a help function that will invoke the constructor with the default values though. My example is not as robust as it should be but it should get you started.
static Func<T> CreateDefaultConstructor<T>(ConstructorInfo ci)
{
var l = new List<object>();
foreach (var p in ci.GetParameters())
{
if (p.IsOptional)
{
l.Add(p.RawDefaultValue);
}
}
return () => (T)ci.Invoke(l.ToArray());
}
The problem is that, in the case of B, it does not have a constructor with no parameters.
Optional arguments are a compile time construct - in the IL, it's a constructor with 2 parameters (which are flagged with attributes). As such, there is no default constructor as far as Reflection is concerned.
To get the one that has more optional parameters or an empty constructor at all, use:
typeof(myClass)
.GetConstructors()
.OrderBy(x => x.GetParameters().Length - x.GetParameters().Count(p => p.IsOptional))
.FirstOrDefault();
When a constructor, or any other method, has optional arguments it doesn't cause the compiler to generate multiple versions of the method. Instead it generates a single method which has all of the specified parameters. The default values are encoded in attributes attached to the method signature. These are used at the call site to make their values optional.
So here there is no default constructor but instead a single one with 2 parameters
Is there any way to do something like this in C#?
public void DoSomething(string parameterA, int parameterB)
{
}
var parameters = ("someValue", 5);
DoSomething(parameters);
Close, but unfortuantely only using object (so you get lots of boxing/unboxing)
public void DoSomething(params object[] parameters)
{
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters); // this way works
DoSomething("someValue", 5); // so does this way
Not today, no. We are at present prototyping exactly that feature for a possible hypothetical future version of C#.
If you can provide a really awesome reason why you want this feature, that would be points towards actually getting it out of prototyping and into a possible hypothetical future release. What's your awesome scenario that motivates this feature?
(Remember, Eric's speculations about possible hypothetical future releases of C# are for entertainment purposes only and are not to be construed as promises that there ever will be such a release or that it will have any particular feature set.)
No need to use reflection if you first store as a delegate, but it does require a strong declaration of the delegate.
public void DoSomething(string parameterA, int parameterB)
{
Console.WriteLine(parameterA+" : "+parameterB);
}
void Main()
{
var parameters = new object[]{"someValue", 5};
Action<string,int> func=DoSomething;
func.DynamicInvoke(parameters);
}
...and you can forget about compile-time type/sanity checking of the parameter list. Probably a bad thing.
You can invoke it through reflection, but that'll incur some overhead:
using System;
using System.Reflection;
namespace SO2744885
{
class Program
{
public void DoSomething(string parameterA, int parameterB)
{
Console.Out.WriteLine(parameterA + ": " + parameterB);
}
static void Main(string[] args)
{
var parameters = new object[] { "someValue", 5 };
Program p = new Program();
MethodInfo mi = typeof(Program).GetMethod("DoSomething");
mi.Invoke(p, parameters);
}
}
}
Of course, if you can change the method signature to take an array, that'll work as well, but that will look worse in my opinion.
nope - this is not possible.
Maybe this way is more "clean":
// standard method calling
DoSomething( "Johny", 5 );
// since C# 4.0 you can used "named parameters"
DoSomething( name: "Johny", number: 5 );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters( "Johny", 5 ) );
// calling with parameter's "container"
DoSomething( new DoSomethingParameters{ Name = "Johny", Number = 5 } );
// calling with callback for parameters initialization
DoSomething( p => { p.Name = "Johny"; p.Number = 5; } );
// overload of DoSomething method with callback, which initialize parameters
public void DoSomething( Action<DoSomethingParameters> init ) {
var p = new DoSomethingParameters();
init( p );
DoSomething( p );
}
// overload of DoSomething method for calling with simple parameters
public void DoSomething( string name, int number ) {
var p = new DoSomethingParameters( name, number );
DoSomething( p );
}
// the "main executive" method which is "doing the work"
// all posible parameters are specified as members of DoSomethingParameters object
public void DoSomething( DoSomethingParameters p ) { /* ... */ }
// specify all parameters for DoSomething method
public class DoSomethingParameters {
public string Name;
public int Number;
public DoSomethingParameters() { }
public DoSomethingParameters( string name, int number ) {
this.Name = name;
this.Number = number;
}
}
Inspired by Steven's answer:
static public void Execute<T1, T2>(this Tuple<T1, T2> parameters, Action<T1, T2> action)
{
action(parameters.Item1, parameters.Item2);
}
var parameters = Tuple.Create("someValue", 5);
parameters.Execute(DoSomething);
I like Henrik's answer, except that it imposes a somewhat weird syntax: parameters call a method on themselves. I would do it the other way around. Only problem with this approach is that it makes you explicitly cast a method to a delegate.
Anyway, here's the basic idea:
// wrapped code to prevent horizontal overflow
public static void Execute<T1, T2>
(this Action<T1, T2> action, Tuple<T1, T2> parameters) {
action(parameters.Item1, parameters.Item2);
}
And so on (for more Ts).
Usage:
var parameters = Tuple.Create("Hi", 10);
Action<string, int> action = DoSomething;
action.Execute(parameters);
You can also easily do this with a return value:
// wrapped code to prevent horizontal overflow
public static TResult Return<T1, T2, TResult>
(this Func<T1, T2, TResult> func, Tuple<T1, T2> parameters) {
return func(parameters.Item1, parameters.Item2);
}
And so on.
I'd also like to point out that just because you aren't on .NET 4.0, that doesn't mean you can't easily implement your own Tuple<T1, T2, ...> type.
you can do:
public void DoSomething(string parameterA, int parameterB)
{
}
var func = (Action)(() => DoSomething("someValue", 5));
func();
You can do this (.NET 4.0):
var parameters = Tuple.Create("someValue", 5);
DoSomething(parameters.Item1, parameter.Item2);
If they're all the same type, yes, you can do something to this effect:
public void Print(params string[] args) {
foreach (string arg in args) {
Console.WriteLine(arg);
}
}
// ...
Print("apple", "banana");
Print("apple", "banana", "cherry");
Print("apple", "banana", "cherry", "doughnut");
Otherwise, no, you can't expand parameters in place like that without using reflection. C# doesn't have the equivalent of Ruby's splat operator.
If you don't want to change the method signature why not declare a new method with the appropriate signature and use that as a proxy. Like
public void DoSomething(string parameterA, int parameterB)
{
// Original do Something
}
public void DoSomething(object[] parameters)
{
// some contract check whether the parameters array has actually a good signature
DoSomething(parameters[0] as string,(parameters[1] as int?).Value);
}
var parameters = new object[]{"someValue", 5};
DoSomething(parameters);
You can also try out some of the stuff LinFu.Reflection provides, like Late Binding. With it you can do something like this:
var dosomethingobject = new ObjectThatHasTheDoSomething();
DynamicObject dynamic = new DynamicObject(dosomethingobject);
var parameters = new object[]{"someValue", 5};
dynamic.Methods["DoSomething"](parameters);
For this you need that the DoSomething method is inside an object.
"var" just represents a particular type, it's effectively shorthand for writing a type name. In the above you're not specifying any type. The only way to do this is to make a parameter class to represent the inputs in bulk...
public void DoSomething(Parameters param)
{
...
}
var param = new Parameters("someValue", 5);
DoSomething(param);
...but this is only going to be useful in specific circumstances. You could make multiple Parameters constructors to represent different arrangements of parameters, but the function you're calling will only take ONE input - the Parameters object. So with this you're really undermining the ability to overload a function.
So, in short, no. =)
How about this in .NET 4 (for the sake of curiosity)
public void DoSomething(string parameterA, int parameterB)
{
}
public void Helper(dynamic parameter)
{
DoSomething(parameter.Parameter1, parameter.Parameter2);
}
var parameters = new {Parameter1="lifeUniverseEverything", Parameter2=42};
Helper(parameters);
My application is processing IList's. ILists of different user defined types. I'm thinking that i can use reflection to to see what type of object the IList contains and then create a new instance of that type and subsequently add that to the IList itself?
So at any one time I might be processing
IList<Customer> l;
and I'd like to create a new instance of Customer
Customer c = new Customer(0, "None")
and then add that onto the list
l.Add(c);
Obviously doing this dynamically at run-time is the crux of the problem. Hope somebody can give me some pointers. Thanks brendan
Try this:
public static void AddNewElement<T>(IList<T> l, int i, string s)
{
T obj = (T)Activator.CreateInstance(typeof(T), new object[] { i, s });
l.Add(obj);
}
Usage:
IList<Customer> l = new List<Customer>();
l.Add(new Customer(1,"Hi there ..."));
AddNewElement(l, 0, "None");
(EDIT):
Try this then:
public static void AddNewElement2(IList l, int i, string s)
{
if (l == null || l.Count == 0)
throw new ArgumentNullException();
object obj = Activator.CreateInstance(l[0].GetType(), new object[] { i, s });
l.Add(obj);
}
If you can use a parameterless constructor and set the properties afterwards then you can make your method generic, something like:-
void Process<T>(IList<T> list, int x, string y) where T : MyBase, new()
{
T t = new T();
t.X = x;
t.Y = y;
list.Add(t);
}
Where MyBase is the base for your classes which expose the int and string properties. You can use an interface rather than a base class if you want.
You can use the Activator.CreateInstance method to invoke a constructor for a class via its type name (as a string) or an instance of System.Type.
I think you should change your design. You can use abstract factory pattern. Using reflection would degrade performance.
Here is code for factory.
public abstract class MyStore {
public abstract string Name { get; }
public abstract void AddItem(int id, string name);
}
You can consider using interface if your abstract class has no code.
Then create Customer store.
public class CustomerStore : MyStore, IEnumerable<Customer> {
List<Customer> list = new List<Customer>();
public override string Name { get { return "Customer Store"; } }
public override void AddItem(int id, string name) {
list.Add(new Customer(id, name));
}
public IEnumerator<Customer> GetEnumerator() {
return list.GetEnumerator();
}
}
Usage
foreach (MyStore store in List<MyStore>)
store.AddItem(0, "None");
If you want to consider type of store, use
switch (store.Name) {
case "Customer Store":
SomeMethod((CustomerStore)store);
break;
default:
throw new WhatEverException();
}
You could use the Type.GetGenericArguments method to return the type argument of the generic type IList<T>. Then invoke the appropriate constructor.
Type T = l.GetType ( ).GetGenericArguments ( ) [ 0 ];
ConstructorInfo ctor = T.GetConstructor (
new Type [ 2 ] { typeof ( int ), typeof ( string ) } );
System.Diagnostics.Debug.Assert ( ctor != null );
object instance = ctor.Invoke (
new object [ 2 ] { 0, "None" } );
Yes sorry i should have mentioned that the set of objects i will be processing will have a constructor that accepts an int and a string.
The big problem here is: If you don't know the type, how do you know how to make a new one? Not every type in the world has a constructor that takes an int and a string.
The best way to get the type of the IList is to look at the property type of the indexer!
var collectionType = targetList.GetType().GetProperty("Item").PropertyType;
var constructor = collectionType.GetConstructor(Type.EmptyTypes);
var newInstance = constructor.Invoke(null);
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.