4

I'm creating a type at runtime using Reflection.Emit. The problem is that whenever I instantiate an instance of the new type I have to use object or dynamic because the type isn't known at compile time. This works fine except for when I would want another type to implicitly cast to the new type during assignment. The variable happily takes on the new value and it's corresponding type without attempting to cast to its current type.

Is there any way to create a variable of a newly created type that will allow for implicit casting? I'm perfectly happy to give up compile-time checking but I would like these casts to at least be attempted at run-time.

Edit:

Here is an example to make it more clear. This is what happens when you know the type at compile-time:

MyClass a;
//this calls the implicit cast operator and 'a' stays of the same type
a = 5;

and this is what happens if you don't:

Type t = CreateTypeUsingTypeBuilder();
object a = Activator.CreateInstance(t);
//this does not call the implicit cast operator and 'a' just becomes in integer
a = 5;

Also, I'm not surprised at this behavior or asking why it happens. I'm asking if there is any sort of workaround to achieve the desired behavior of having it check for an implicit operator at run-time.

Ivanna
  • 1,197
  • 1
  • 12
  • 22
  • 8
    It's really not clear what you mean, I'm afraid - but if the type doesn't exist at compile-time, it's hard to see how you expect the compiler to know that there'll be an implicit conversion available. If you could give us a concrete example of what you're trying to do, it would really help. – Jon Skeet Feb 08 '16 at 13:15
  • Implicit casting requires knowing at compile time something of the source object's type (to determine which implicit conversion operator to call). You could implement an interface; or use dynamic and provide the necessary implicit conversion operators. – Richard Feb 08 '16 at 13:36
  • You probably want to define an interface that describes what properties and methods this emitted object will have that you wish to use in the application. Emit your code, then cast the result to this interface. The class you create has to implement the interface, obviously. But that'll give you compile time goodness. –  Feb 08 '16 at 13:39
  • @Richard Using `dynamic` results in the same behavior as `object`: it doesn't attempt the casting, instead taking on the type that's being assigned. I tried various things with interfaces but you can't define implicit casting operators in an interface which is what I think you would have to do. – Ivanna Feb 08 '16 at 13:39
  • @Will I don't think that it's possible to define the implicit casting operators in an interface so this doesn't help with my particular problem (though it's very useful in general when dealing with types built at run-time). – Ivanna Feb 08 '16 at 13:43
  • I'd use the interface and avoid "implicit casting" altogether. Who needs implicit casting when I can explicitly cast it to something I know how to use? Implicit casting feh. –  Feb 08 '16 at 13:44
  • @Will Implicit casting has its uses. My specific use case is a library where the newly created types can be easily used as drop-in replacements for existing types in existing code bases. Requiring explicit casting would mean requiring users to make massive changes to their own existing code. In this situation, I would argue that the benefits outweigh the negatives. – Ivanna Feb 08 '16 at 13:50
  • *a library where the newly created types can be easily used as drop-in replacements for existing types in existing code bases* ... ... but ..... but that's what interfaces are for. You define the shape of what you need, then anybody can provide you a "drop in" implementation. All they need to do is ... implement your interface. It's ... it's how this sort of thing is kinda done. Like and stuff. –  Feb 08 '16 at 13:56
  • @Will What if the types are numeric? Then the interface would involve *, /, -, +, and =. The only way to get at assignment is through implicit casting. – Ivanna Feb 08 '16 at 14:03
  • I understand the desire to use them like numerics, but it's always an option to have methods for ops. Anyhow, good luck! –  Feb 08 '16 at 14:06

2 Answers2

2

In order to understand why this is not possible, at least not directly, one needs to understand how implicit conversion operators work in the first place.

When you write something like this

MyNumericType x = new MyNumericType(123);
double y = x;

the compiler realizes that x and y are of different types, and searches MyNumericType to see if there is an implicit conversion operator defined:

public static implicit operator double(MyNumericType n) {
    return n.doubleValue;
}

Once the operator is found, the compiler invokes it as if it were a regular static method (which it is).

When you work with types generated at runtime, you should generate the conversion at runtime as well. For example, if you do this

private static Func<object,object> MakeConverter(Type t1, Type t2) {
    var p = Expression.Parameter*(typeof(object));
    var eFrom = Expression.Convert(p, t1);
    var eTo = Expression.Convert(eFrom, t2);
    var res = Expression.Convert(eTo, typeof(object));
    var lambda = Expression.Lambda<Func<object,object>>(res, new[] { p });
    return (Func<object,object>)lambda.Compile();
}

With this method in place you can do this:

Type runtimeType1 = ...
Type runtimeType2 = ...
var converter = MakeConverter(runtimeType1, runtimeType2);
object objRuntimeType1 = ...
object objRuntimeType2 = converter(objRuntimeType1);
Community
  • 1
  • 1
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • The `Expression.Convert` method required type known on compile time. Can the lambda expression be rewritten to support something like t1 = p.getType() on runtime? – mvorisek Mar 23 '19 at 23:22
  • @Mvorisek `Expression.Convert` method does not require the type to be known at compile time. `Type t1` variable could very well represent a type discovered dynamically at run-time. – Sergey Kalinichenko Mar 24 '19 at 00:56
0

If the idea is, as I suppose in this context, to create wrapper classes for known types in runtime, then I have a few ideas you could try.

One is to add a parameterized constructor in the wrapper type, that takes an object of the wrapped type as the parameter and then uses that object to initialize the wrapper object (like you would do in an implicit conversion operator). Then, knowing that you can use e.g. an integer as a constructor parameter, you could simply do this:

Type t = CreateTypeUsingTypeBuilder();
object a = Activator.CreateInstance(t, 5);

This will search the type for a constructor that could be invoked with the given object. You might get MissingMethodException if no matching public constructor is found.

Another idea is to create either an interface or an abstract base type for your types built in runtime, that requires the derived classes to implement some sort of conversion method. When you derive your built types from this abstract class or make them implement the interface, you can cast the object created with the Activator to that class or that interface and then call the conversion method already normally. If you make your interface generic, you could have multiple different conversion implementations.

public interface IMyWrapper<T>
{
    IMyWrapper<T> Convert(T value);
}

While there is no way to use an implicit operator implicitly, I think you could achieve your ultimate goal of converting an integer to your built type in some other way, including one or the other hinted above.

xjuice
  • 300
  • 1
  • 8