How do I add a globally available MetaMethod on Object in Groovy? - groovy

(this is a generalized example)
I'd like to create a utility method that can be called on any object, it'll have a signature like:
class StringMetaData {
Object value
String meta
}
Object.metaClass.withStringMetaData = { meta ->
new StringMetaData(delegate, meta)
}
With the idea that then anywhere in my program I could do something like:
def foo = 1.withStringMetaData("bar")
And now I can grab foo.value for the value or foo.meta for the attached String.
Within a local context, I'm able to define this meta method on Object, but I'd like to make it available globally within my application, what's the right way to make this metamethod available everywhere?

Perhaps a groovy extension module could help you. I never tried it myself, but the documentation states, that you can add custom methods to JDK classes.

Related

Is the `def` keyword optional? If so, why use it?

I am aware that a variable can be dynamically typed with the def keyword in Groovy. But I have also noticed that in some circumstances it can be left out, such as when defining method parameters, eg func(p1, p2) instead of func(def p1, def p2). The latter form is discouraged.
I have noticed that this is extendable to all code - anytime you want to define a variable and set its value, eg var = 2 the def keyword can be safely left out. It only appears to be required if not instantiating the variable on creation, ie. def var1 so that it can be instantiated as a NullObject.
Is this the only time def is useful? Can it be safely left out in all other declarations, for example, of classes and methods?
Short answer: you can't. There are some use cases where skipping the type declaration (or def keyword) works, but it is not a general rule. For instance, Groovy scripts allow you to use variables without specific type declaration, e.g.
x = 10
However, it works because groovy.lang.Script class implements getProperty and setProperty methods that get triggered when you access a missing property. In this case, such a variable is promoted to be a global binding, not a local variable. If you try to do the same on any other class that does not implement those methods, you will end up getting groovy.lang.MissingPropertyException.
Skipping types in a method declaration is supported, both in dynamically compiled and statically compiled Groovy. But is it useful? It depends. In most cases, it's much better to declare the type for a better readability and documentation purpose. I would not recommend doing it in the public API - the user of your API will see Object type, while you may expect some specific type. It shows that this may work if your intention is to receive any object, no matter what is its specific type. (E.g. a method like dump(obj) could work like that.)
And last but not least, there is a way to skip type declaration in any context. You can use a final keyword for that.
class Foo {
final id = 1
void bar(final name) {
final greet = "Hello, "
println greet + name + "!"
}
}
This way you can get a code that compiles with dynamic compilation, as well as with static compilation enabled. Of course, using final keyword prevents you from re-assigning the variable, but for the compiler, this is enough information to infer the proper type.
For more information, you can check a similar question that was asked on SO some time ago: Groovy: "def" keyword vs concrete type
in Groovy it plays an important role in Global and Local variable
if the variable name is same with and without def
def is considered local and without def its global
I have explained here in detail https://stackoverflow.com/a/45994227/2986279
So if someone use with and without it will make a difference and can change things.

Create Map of classes in TypeScript

I've got a rendering engine, much like React where I need to store classes rather than instances in an object for compiling.
So for example, I have a Button component that I would like to be able to dynamically instantiate. Doing this would be as easy as
new components["Button"]
For this, I need a list of all possible classes. So I've got a Dictionary interface declared like so:
interface Dictionary<T> {
[Key: string]: T;
}
This works well, I'm easily able to add objects to this dictionary. Except if I have an object:
const components: Dictionary<Component> = {
Button: Button
}
Then I get an error because Button is a class, rather than an instance. Here, the issue is, I don't want to define the dictionary as Dictionary<Function> because that would mean I allow any function into the dictionary. Specifically, I only want to allow classes into the dictionary that extend the Component class.
How would I achieve this?
You also need to define the signature of the constructor (which makes sense if you think about it), but you do the following:
interface ComponentClass {
new (a: number): Component;
}
(The signature of the constructor is probably not "number", but put in whatever it is.)

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

How to auto-generate early bound properties for Entity specific (ie Local) Option Set text values?

After spending a year working with the Microsoft.Xrm.Sdk namespace, I just discovered yesterday the Entity.FormattedValues property contains the text value for Entity specific (ie Local) Option Set texts.
The reason I didn't discover it before, is there is no early bound method of getting the value. i.e. entity.new_myOptionSet is of type OptionSetValue which only contains the int value. You have to call entity.FormattedValues["new_myoptionset"] to get the string text value of the OptionSetValue.
Therefore, I'd like to get the crmsrvcutil to auto-generate a text property for local option sets. i.e. Along with Entity.new_myOptionSet being generated as it currently does, Entity.new_myOptionSetText would be generated as well.
I've looked into the Microsoft.Crm.Services.Utility.ICodeGenerationService, but that looks like it is mostly for specifying what CodeGenerationType something should be...
Is there a way supported way using CrmServiceUtil to add these properties, or am I better off writing a custom app that I can run that can generate these properties as a partial class to the auto-generated ones?
Edit - Example of the code that I would like to be generated
Currently, whenever I need to access the text value of a OptionSetValue, I use this code:
var textValue = OptionSetCache.GetText(service, entity, e => e.New_MyOptionSet);
The option set cache will use the entity.LogicalName, and the property expression to determine the name of the option set that I'm asking for. It will then query the SDK using the RetrieveAttriubteRequest, to get a list of the option set int and text values, which it then caches so it doesn't have to hit CRM again. It then looks up the int value of the New_MyOptionSet of the entity and cross references it with the cached list, to get the text value of the OptionSet.
Instead of doing all of that, I can just do this (assuming that the entity has been retrieved from the server, and not just populated client side):
var textValue = entity.FormattedValues["new_myoptionset"];
but the "new_myoptionset" is no longer early bound. I would like the early bound entity classes that gets generated to also generate an extra "Text" property for OptionSetValue properties that calls the above line, so my entity would have this added to it:
public string New_MyOptionSetText {
return this.GetFormattedAttributeValue("new_myoptionset"); // this is a protected method on the Entity class itself...
}
Could you utilize the CrmServiceUtil extension that will generate enums for your OptionSets and then add your new_myOptionSetText property to a partial class that compares the int value to the enums and returns the enum string
Again, I think specifically for this case, getting CrmSvcUtil.exe to generate the code you want is a great idea, but more generally, you can access the property name via reflection using an approach similar to the accepted answer # workarounds for nameof() operator in C#: typesafe databinding.
var textValue = entity.FormattedValues["new_myoptionset"];
// becomes
var textValue = entity.FormattedValues
[
// renamed the class from Nameof to NameOf
NameOf(Xrm.MyEntity).Property(x => x.new_MyOptionSet).ToLower()
];
The latest version of the CRM Early Bound Generator includes a Fields struct that that contains the field names. This allows accessing the FormattedValues to be as simple as this:
var textValue = entity.FormattedValues[MyEntity.Fields.new_MyOptionSet];
You could create a new property via an interface for the CrmSvcUtil, but that's a lot of work for a fairly simple call, and I don't think it justifies creating additional properties.

Pass a dynamic variable in a static parameter of a method in C# 4

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.

Resources