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.
Related
I have a Groovy script that lets the user define some dynamic properties and methods and later executes a user-defined closure. A script would look like this:
// init properties and methods dynamically at runtime
context.prop1 = "Some test value"
context.method1 = { String input ->
"exec " + input.toUpperCase()
}
// "this" is set to the context variable from above
run {
println method1( prop1 )
}
So in the beginning of the script, a context is initialized with user-defined properties (e.g. prop1) and methods (e.g. method1). The context is then used as this pointer in the run closure. I have achieved this by dynamically extending the meta class of the context and setting the context as delegate of the run closure (with DELEGATE_FIRST as resolves strategy).
Currently I am struggling at type checking. Before executing the run closure, I would like to check if method1 really expects prop1. I have looked into the DelegatesTo annotation, but that doesn't seem to work for dynamically extended objects. I have also played with the AST, but since my knowledge on that topic is limited, I haven't come up with a solution. If what I want to achieve is possible, any pointers in the right direction would be greatly appreciated.
You want to add a method to a context at runtime and then type check this before execution of that method.
Type checking is done at compile time. That is before anything of your program is executed. There is normally no chance this can ever check anything that will only happen at runtime, unless you have a way to statically declare it and give the compiler the power to do the check. But this means normally, you will have to do static compilation.
One way would be to use type checking extensions, but I think in your case that might be overkill. A more simple way would be to use extension modules. And the most simple way would be to use custom script base class.
But for any of these solution you will need static compilation to really have type checking, same for DelegatesTo (which is more used in combination with extension modules). For a type checked DSL a mix of type checking extensions and extension modules can work very well. But you will of course loose more dynamic features of the language and some simplicity.
If a mocked method is passed a generic type as a parameter, it is easy to generate the same response regardless of its value by using methods such as anyInt(), anyChar(), anyString(), etc.
Is it possible to do this where the parameter must be a particular type of Object?
(For example, anyCar(), anyVehicle(), etc.)
The matcher isA(Class<T> clazz) provides this functionality.
For example -
isA(Car.class), isA(Vehicle.class)
I need to build a grammer containing a cross reference, which may be invalid, i.e. points to a nonexisting target. A file containing such a reference should not yield an error, but only a warning. The generator would handle this as as a special case.
How can I do this with XText?
It's not possible to create valid cross references to non-existing targets in EMF.
I would suggest to go with EAttributes instead of EReferences:
Change the feature=[EClass|ID] by feature=ID in {YourDSL} grammar.
Provide a scope calculation utility like it's done in *scope_EClass_feature(context, reference)* method in the {YourDSL}ScopeProvider class. As this scoping methods simply use the eType of the given reference the reimplementation should be straightforward.
Use this scope calculation utility in {YourDSL}ProposalProvider to propose values for the introduced EAttribute.
Optionally you can use this utility in a validation rule to add a warning/info to this EAttribute if it's not "valid".
Finally use the utility in your generator to create output based on valid target eObjects.
I also ran into this problem when creating a DSL to provide declerations of variables for a none-declerative language for a transition pahse. This method works but ask yourself if you realy want to have those nasty may-references.
You can drop the auto generated error in you UI module only. To do so, provide an ILinkingDiagnosticMessageProvider and override the function getUnresolvedProxyMessage:
class DSLLinkingDiagnosticMessageProvider extends LinkingDiagnosticMessageProvider {
override getUnresolvedProxyMessage(ILinkingDiagnosticContext context) {
if(context.context instanceof YourReference) {
// return null so the your error is left out
null
} else {
// use super implementation for others
super.getUnresolvedProxyMessage(context)
}
}
}
All linker-errors for YourReference will be missed. But be aware that there will be a dummy referenced object with all fealds null. Exspecialy the name ist lost and you can not set it due to a CyclicLinkingException. But you may create a new method that sets the name directly.
Note that the dummy object will have the type you entered in your gramma. If its abstract you can easily check witch reference is not linked.
This is what I am trying to do:
public void method(int myVal, string myOtherVal)
{
// doing something
}
dynamic myVar = new SomeDynamicObjectImplementer();
method(myVar.IntProperty, myVar.StringProperty);
Note that my properties are also DynamicObjects. My problem is that the TryConvert method is never called and that I get a runtime error saying the method signature is invalid.
The following is working great:
string strVar = myVar.StringProperty;
int intVar = myVar.IntProperty;
And I would like to avoid
method((int)myVar.IntProperty, (string)myVar.StringProperty);
Is it possible to override something in DynamicObject to allow this? (or something else)
Thank you
The problem is your assumption that it will try a dynamic implicit convert on arguments of an dynamic invocation to make a method call work, this is not true.
When your arguments aren't statically typed, it will use the runtime type to find the best matching method (if the runtime type matches the static rules for implicit conversion to the argument type this will work too), since your your IntProperty,StringProperty seem to be returning a DynamicObject rather than an Int and a String or something that could statically be converter implicitly, this lookup will fail.
If SomeDynamicObjectImplementer could actually return an Int for IntProperty and a String for StringProperty your method call for without casting would actually work. It's also probably a better dynamic typing practice if you data type is based on the actually type of data rather than usage using try convert. You could add actually implicit convert methods for every possible type that you could return to that returned DynamicObject type, but that could cause strange resolution issues to depending on how much you are overloading.
However, another option to keep your dynamic implementation the same is to mix a little controlled static typing in, you can use ImpromputInterface (in nuget) to put an interface on top of a dynamic object, if you do that then the TryConvert method would be called on your returned DynamicObjects.
public interface ISomeStaticInterface{
int IntProperty {get;}
string StringProperty {get;}
}
...
var myVar = new SomeDynamicObjectImplementer().ActLike<ISomeStaticInterface>();
method(myVar.IntProperty, myVar.StringProperty);
Instead of using myVar.IntProperty can't you just put them in variables first, like you already did, and then use then for your method?
so method(intVar , strVar); seems fine. At least more elegant than casting.
Of course, if you're already certain your object will have IntProperty and StringProperty, why not just make an actual object with those properties instead?
Why are you doing the cast?
method(myVar.IntProperty, myVar.StringProperty);
should compile.
If the two properties must be the types suggested by the names then they shouldn't be dynamic.
I'm in a situation where I need to return an object of an anonymous type from a method, is it a good idea to use dynamic as a return type? what considerations to take?
public dynamic MyMethod()
{
// process and return the object of an anonymous type
}
It doesn't make any sence, you can return object with the same effect.
P.S.: Also anonymous types are not that good as return types.
Yes it has sense If you "guarantee" that you'll always return an object with some characteristics , with an Id for example (ignoring that perhaps it would be better to use an Interface)
public dynamic MyMethod()
{
var temp = new ExpandoObject();
temp.Id = 5;
return temp;
}
Console.WriteLine(MyMethod().Id);
So if you guarantee that all your objects can Turn Left-Right but you don't guarantee if they are airplanes, cars, motos, boats. (so it's good if you are doing Duck typing When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.)
Note that if you then need to reflect on your objects, it can become ugly: How do I reflect over the members of dynamic object?
Returning a dynamic object does have the benifit of allowing you to access the properties from the anonmymous type without using reflection (albeit without intellisense). If you take this approach you need to make sure that the properties on the anonymous type match what you are accessing on the dynamic object. Otherwise you will get runtime errors
However, I would suggest you consider returning a concrete type instead