0

Intro

To create instances on the fly via reflection, we could use:

Activator.CreateInstance 

The downside to this is that this returns an object, while I really need the concrete type and since I only know the runtime type I can't cast.

To accomplish this, we can use

Activator.CreateInstance<T>

Which returns a T, but since I don't know T at compile time, this is no use either. At first glance anyway.

Currently I'm using dynamic for this, in a special kind of way:

//I pass the runTimeType as an ITopSecret

// runTimeType implements ITopSecret
dynamic concreteTypeInstance = Activator.CreateInstance(runTimeType);

// Now we just have an empty RunTimeType. 
// I can use the passed runTimeType to fill the newly created object
concreteTypeInstance = runTimeType

// Then I call ApplyCurrentValues.
// Can't pass runTimeType, because it's ITopSecret and
// EF doesn't figure out the actual runtime type.
context.ApplyCurrentValues(concreteTypeInstance)

Before this line some sanity checks are performed. For example I know the runtime type is always a certain ITopSecret at this point, otherwise the statement can't get hit.

So presumably this is reasonably safe. It does exactly what I want, with 1 line of code, which seems great.

However I'm not sure this is the intended way of using dynamic and if I'm setting the door open for nasty stuff.

Why do I want this

Currently we have 1000s of lines of boilerplate code in many Update methodes across various services. This is handcrafted, thus error-prone, repetetive, violates DRY and makes it harder for new people. Furthermore this makes the methods unclear by losing focus on business logic and, frankly, is just plain ugly. All the usual suspects ;)

So I'm writing some abstract/generic code to factor out all that repetitive stuff. Which is a very nice and cool bit of software to write, but leaves me with (mostly) runtime info.

Under the surface these methods all use Entity Framework and its ApplyCurrentValues method. This method requires a concrete, instantianted, type and hence my questions.

Hope this is clear enough :)

Questions

  • Is this an OK way to use dynamic, considering I perform do some sanity checks before actually using it?
  • I feel that there's a way using reflection to accomplish this. That might be worse in terms of performance, but I'm very curious if this can be done. Is it possible to create the generic Activator.CreateInstance<T> using reflection?
  • Are either possibilities bad and should I take a different approach entirely? However not knowing the concrete types at run-time, but needing them anyway is not something I can move away from.
Apeiron
  • 602
  • 6
  • 17
  • 1
    You should just cast it to the interface. – SLaks Nov 17 '16 at 17:37
  • Sadly I can't, EF won't let me ;) – Apeiron Nov 17 '16 at 17:38
  • 2
    Huh? What does EF have to do with anything? – SLaks Nov 17 '16 at 17:40
  • What do you do with that dynamic then? If you call some methods on it, what type those methods belong to? If you know the type, why you don't cast to it ((ITopSecretObject) Activator.CreateInstance(runTimeType) )? – Evk Nov 17 '16 at 17:40
  • 1
    "Is it possible to create the generic `Activator.CreateInstance` using reflection?" Yes, but don't. Use `Type.GetConstructor` instead if you have a type handy anyway. To instantiate `ApplyCurrentValues` with a type known only at runtime, see [this question](http://stackoverflow.com/questions/232535/) (which also applies to `CreateInstance`, but, just don't. `CreateInstance` is slow as molasses.) – Jeroen Mostert Nov 17 '16 at 17:45
  • @SLaks EF is the underlying ERM, it can't handle ApplyCurrentValues to an interface, needs an implementation i.e ApplyCurrentValues(ITopSecret) is not allowed. – Apeiron Nov 17 '16 at 17:49
  • @Evk First an 'empty' object is created using CreateInstace and the runtime type information. Then the values are copied in it (indeed from something passed as an ITopSecret). Then that new object is saved using ApplyCurrentValues. Seems a bit meh, right :) Will clarify in the question. – Apeiron Nov 17 '16 at 17:49
  • @JeroenMostert Thanks, will look in to that :) – Apeiron Nov 17 '16 at 17:52
  • 1
    @Apeiron [`ObjectContext.ApplyCurrentValues`](https://msdn.microsoft.com/en-us/library/dd487246(v=vs.110).aspx) may require the concrete type, but you can alternatively locate the object in the `ObjectStateManager` manually, call [`ObjectStateEntry.ApplyCurrentValues`](https://msdn.microsoft.com/en-us/library/system.data.objects.objectstateentry.applycurrentvalues(v=vs.110).aspx) and avoid the whole problem, can't you? –  Nov 17 '16 at 17:53
  • @hvd Thanks for the tip, will look into this immediately as well :) – Apeiron Nov 17 '16 at 17:55

0 Answers0