using dynamic with reflection - c#-4.0

I've heared that the best practice to create an instance using reflection is by using a dynamic type variable.
What it means is that when we use the Activator.CreateInstance() method(that returns object) we assign it into a dynamic type instead of object type:
dynamic dog = Activator.CreateInstance("Zoo.Dog");
dog.Bark();
Instead of:
object dog = Activator.CreateInstance("Zoo.Dog");
Dog realDog = (Dog)dog;
realDog.Bark();
Is there any good reason to use dynamic other than the lack of casting?

If you have access to the type you are creating your instance from, then there is no need to use a dynamic type. You might need to use a dynamic type if you do not have access (in a static way) to the type, for instance when loading dynamically an assembly. If you use a dynamic type instead of a known type, each type you call a member of your instance that will use reflection under the hood. Besides, you won't have intellisense using dynamic types.
You can use the generic method CreateInstance<T> from the Activator class to create your instance.
Dog dog = Activator.CreateInstance<Dog>();
dog.Bark();
The dynamic keyword makes easier the interaction with dynamic languages (IronPython, IronRuby for instance) (Dynamic Language Runtime DLR) or COM Interop APIs, but it is not recommended (nor needed) to use it with known types.

Related

Generic type vs dynamic vs object

I want to make the return type of my method generic. The caller will decide which type it should expect.
Actually my method will be a member of interface and the class which will implement it will have a decision making block to delegate the work to other methods.
Hence I want to make the return type of the interface method as generic.
I can achieve this by using dynamic or object keyword or c# generic type.
I am not able to figure it out which will be the best option to achieve it and what are the limitations and advantages of each type.
public interface ICoreWrapper
{
Response<T> ExecuteDeviceCommand<T>(DeviceCommand deviceCommand, object param = null);
}
Please suggest me.
Thanks in advance.
If you do not know the type at compile time you could use dynamics but they will be slower because they are using runtime invocation and less safe because if the type doesn't implement the method you are attempting to invoke you will get a runtime error.
Use dynamic return type, Based on the input type return the appropriate object.

Cannonical way to do circular dependency in Nim

Suppose we have two modules: one defines an Object and one defines an ObjectFactory. The Object needs to have access to the ObjectFactory use some of its functions, and the ObjectFactory needs access the Object to be able to instantiate Objects.
What is the cannonical way to solve this in Nim if the Object is implemented in a module and the ObjectFactory is implemented in another module?
I am assuming that the issue here is with mutually recursive types, i.e. where the declarations of two or more types refer to one another. Methods or procedures that refer to one another are handled fine by mutually recursive imports, though one has to be careful with module initialization in this case.
As in most other languages that normally require mutually recursive types to be within the same module/compilation unit, there are two principal answers.
One solution is to have the two types within the same module that is imported by both the module that declares the object type and the module that declares the factory type (both types still need to be part of the same type clause). E.g., you create a separate file, called something like factory_types.nim, and put both types in it:
type
ObjectFactory = ref object
lastValue: Object
x: proc(): Object
Object = ref object
factory: ObjectFactory
This module would then be imported by both the module implementing the object and the module implementing the factory.
The other solution, where you can keep each type in its module, is parametric polymorphism, where a type parameter is used as a forward declaration. E.g., you do:
type
ObjectFactory[TargetType] = ref object
lastValue: TargetType
generator: proc(): TargetType
and elsewhere:
type
Object = ref object
factory: ObjectFactory[Object]

In Groovy, can I override java-style casting syntax on POJO classes?

I would like to be able to use plain java-style implicit/explicit casting instead of asType overrides so that sources written in Java work properly. I've overridden asType on String similarly to the approach suggested in How to overload some Groovy Type conversion for avoiding try/catch of NumberFormatException? like:
oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = {Class typ ->
if (Foo.class.isAssignableFrom(typ)) {
Foo.myCast(delegate)
} else {
oldAsType.invoke(delegate,typ)
}
}
I'd like all of these options to work:
// groovy
String barString
Foo foo = barString asType(Foo.class) // asType works but
Foo foo = barString // implicit cast fails
Foo foo = (Foo) barString // explicit cast fails
The latter two fail because groovy is using DefaultTypeTransformation.castToType, which doesn't attempt to invoke new Foo() unless the object to be cast is either one of a slew of special cases or is some sort of Collection type.
Note that the solution Can I override cast operator in Groovy? doesn't solve the issue because the code that is doing the casting is regular Java code that I cannot alter, at least not at the source code level. I'm hoping that there is either a secret hook into casting or a way to override the static castToType method (in a Java class, called by another Java class - which Can you use Groovy meta programming to override a private method on a Java class says is unsupported)... or some other clever approach I haven't thought of.
Edit: The question is about using Java-style casting syntax, essentially to use groovy facilities to add an autoboxing method. Groovy calls this mechanism "casting," for better or worse (see DefaultTypeTransformation.castToType as referenced above). In particular, I have replaced an enum with a resourced class and want to retain JSON serialization. Groovy's JSON package automatically un/marshals enum values of instance members to strings and I'm trying to make the replacement class serialize compatibly with a minimal changes to the source code.
Part of the problem here is you are confusing conversion with casting. Using the "as" operator is not the same thing as imposing a cast. They seem similar, but they serve separate purposes.
Foo foo = (Foo) barString
That doesn't say something like "create a Foo out of barString". That says "Declare a reference named foo, associate the static type Foo with that reference and then point that reference at the object on the heap that the reference barString currently points to.". Unlike languages like C++, Groovy and Java do not allow you to ever get in a situation where a reference points at an object that is of a type that is incompatible with the reference's type. If you ever got into a situation where a Foo reference was pointing to a String on the heap, that would represent a bug in the JVM. It cannot be done. You can come up with ways to create Foo objects out of String objects, but that isn't what the code above is about.
The answer appears to be "no". Absent a rewrite of the DefaultTypeTransformation.castToType to allow for this sort of metaprogramming, the implication is to use another implementation strategy or use a different language.

Interfacing and extending ApplicationClass

I am trying to write a module in F#, making it easier working with Excel, by extracting rows, columns, etc. along with type casting and so on. One of the first things I wanted to do, was to extend various classes/types to implement the IDisposable interface. I tried to write something like the following
type Excel.ApplicationClass with
interface IDisposable with
member this.Dispose() =
this.excel.Quit()
Marshal.ReleaseComObject(this.excel) |> ignore
What I wasn't aware of, was that I would get the following error "All implemented interfaces should be declared on the initial declaration of the type".
My question is the following: Since I am not allow to extend a type with an interface - what else could I do?
If you inherit from the base class it can work, like this
type myAppClass() =
inherit Excel.ApplicationClass() //may not be correct signature - you need to match the base constructor
interface IDisposable with
member this.Dispose() =
//function body

Storing object in Esent persistent dictionary gives: Not supported for SetColumn Parameter error

I am trying to save an Object which implements an Interface say IInterface.
private PersistentDictionary<string, IInterface> Object = new PersistentDictionary<string, IInterface>(Environment.CurrentDirectory + #"\Object");
Since many classes implement the same interface(all of which need to cached), for a generic approach I want to store an Object of type IInterface in the dictionary.
So that anywhere I can pull out that object type cast it as IInterface and use that object's internal implementation of methods etc..
But, as soon as the Esent cache is initialized it throws this error:
Not supported for SetColumn
Parameter name: TColumn
Actual value was IInterface.
I have tried to not use XmlSerializer to do the same but is unable to deserialize an Interface type.Also, [Serializable] attribute cannot be used on top of a Interface, so I am stuck.
I have also tried to make all the implementations(classes) of the Interface as [Serializable] as a dying attempt but to no use.
Does any one know a way out ? Thanks in advance !!!
The only reason that only structs are supported (as well as some basic immutable classes such as string) is that the PersistentDictionary is meant to be a drop-in replacement for Dictionary, SortedDictionary and other similar classes.
Suppose I have the following code:
class MyClass
{
int val;
}
.
.
.
var dict = new Dictionary<int,MyClass>();
var x = new MyClass();
x.val = 1;
dict.Add(0,x);
x.val = 2;
var y = dict[0];
Console.WriteLine(y.val);
The output in this case would be 2. But if I'd used the PersistentDictionary instead of the regular one, the output would be 1. The class was created with value 1, and then changed after it was added to the dictionary. Since a class is a reference type, when we retrieve the item from the dictionary, we will also have the changed data.
Since the PersistentDictionary writes the data to disk, it cannot really handle reference types this way. Serializing it, and writing it to disk is essentially the same as treating the object as a value type (an entire copy is made).
Because it's intended to be used instead of the standard dictionaries, and the fact that it cannot handle reference types with complete transparency, the developers instead opted to support only structs, because structs are value types already.
However, if you're aware of this limitation and promise to be careful not to fall into this trap, you can allow it to serialize classes quite easily. Just download the source code and compile your own version of the EsentCollections library. The only change you need to make to it is to change this line:
if (!(type.IsValueType && type.IsSerializable))
to this:
if (!type.IsSerializable)
This will allow classes to be written to the PersistentDictionary as well, provided that it's Serializable, and its members are Serializable as well. A huge benefit is that it will also allow you to store arrays in there this way. All you have to keep in mind is that it's not a real dictionary, therefore when you write an object to it, it will store a copy of the object. Therefore, updating any of your object's members after adding them to the PersistentDictionary will not update the copy in the dictionary automatically as well, you'd need to remember to update it manually.
PersistentDictionary can only store value-structs and a very limited subset of classes (string, Uri, IPAddress). Take a look at ColumnConverter.cs, at private static bool IsSerializable(Type type) for the full restrictions. You'd be hitting the typeinfo.IsValueType() restriction.
By the way, you can also try posting questions about PersistentDictionary at http://managedesent.codeplex.com/discussions .
-martin

Resources