mercredi 19 septembre 2018

Get a Property Type without an Instance

Is there a way through reflection to get the type of a property without instantiating the class?

I have two string variables, one holding the class name and one holding the property name. I then need to get the property Type (int, string, etc.). I don't want to instantiate the class. Any suggestions? Thanks





C# Reflection Interface Type and Unity

hope someone can help. I use Unity and app.config to dynamically load and run methods in certain assemblies. In our main application I used to do something like ...

var ourProcess = container.Resolve<IProcessing>(new ResolverOverride[] { new ParameterOverride("parameter1", value1) });
ourProcess.ExecuteProcess(parameterValues); 
// parameterValues a string list, all of my processes use this main calling mechanism.
// there are many other interfaces i a number of other assemblies along with IProcessing

However in the main application I need a reference to the IProcessing interface and that's of little use because if I add another processing assembly I don't want to reference said new assembly in the main application, rebuild, retest and redistribute, I just want Unity to resolve and call as appropriate.

I've tried using reflection along the lines of ...

Assembly asm = Assembly.LoadFrom("CompName.Application.Processing.dll");
foreach (Type type in asm.GetTypes())
{
    if (type.GetInterface("IProcessing") != null)
    {
        var ourProcess = container.Resolve<type> (new ResolverOverride[] { new ParameterOverride("parameter1", value1) });
        oSummary = ourProcess.ExecuteProcess(parameterValues);
    }
}
// at runtime we will know the strings "CompName.Application.Processing.dll" and "IProcessing"

However at compile time we get the "'type' is a variable but is used like a Type", fair enough.

I've tried typeof(type), type.GetType() and Type(type) to no avail, all resulting in different compiler errors.

So, the question is how can I use the string name of the interface I require to instantiate and run a process in a non-referenced assembly resolved and loaded by Unity? I'm a little new to Unity and this is the first time using reflection so please go easy on me. I do feel though that this should be relatively easy and feel I am missing something fundemental.

I have searched for the previous few hours and tried one or two things but none have given me the results I need. It would be time consuming to remove my Unity driven code throughout the systems.

Any input appreciated, thanks.





Type search fails

I use PowerShell in version 5+ and I loaded external DLLs into the AppDomain of PS.

In the program I would like to compare types and to determine a Type, the System.Type.GetType method seems the right fit.

The script snapshot looks as follows:

[System.Reflection.Assembly]::LoadFile("..path..\Oracle.ManagedDataAccess.dll") | Out-Null
$Type = [System.Type]::GetType("Oracle.ManagedDataAccess.Client.OracleCommand", $true, $true)

But PowerShell throws an exception (roughly translated, not the original english message):

Exception while calling "GetType" with 3 arguments:  "The Type
"Oracle.ManagedDataAccess.Client.OracleCommand" in the assembly "Anonymously Hosted DynamicMethods 
Assembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" could not be load."
In script.ps1:2 Character:1
+ $Type = [System.Type]::GetType("Oracle.ManagedDataAccess.Client.Oracl ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : TypeLoadException

Is there a possibility to don't check in the 'Anonymously Hosted DynamicMethods Assembly' but to check the current loaded AppDomain space to find the Type specified?





Updating nested property value via a string path using expression

The Problem to solve

I want to be able to update the property prop using the fictive method Update. To do so, i would like to call the method like this:

Root obj = /* ... */;
Update(obj, "sub/sub/prop", "foobar");

How would i eg. build some Expression tree to do this?

Scenario

class Sub2
{
    public string prop { get; set; }
}
class Sub1
{
    public Sub2 sub { get; set; }
}
class Root
{
    public Sub1 sub { get; set; }
}
class Main
{
    //...
    void Update(object obj, string navigation, object newval) { /* magic */ }
}

Full Problem

I need to be able to serialize single fields from some object (already solved, method head public void Serialize<TProperty>(T obj, Stream s, Expression<Func<T, TProperty>> exp)) and update a corresponding field on a server application. Only that field is allowed to be updated, some classes are nested way too deep to allow for solutions like "just use some ID stuff and a switch to then put the value into the right field" which is why this approach was chosen.





mardi 18 septembre 2018

How can I load my Yaml file into a case class?

I have a Scala application that needs to read in a Yaml file and load it into a Scala case class. I'm using snakeyaml to do the job, but it seems that the load function can't use my case class's constructor. Below is an example of what I'm doing...

Yaml File:

"name": "Jon"
"age": 50
"gender": "male"

Case Class:

final case class Person(
    name: String, 
    age: Int,
    gender: String
)

Code to extract and load Yaml:

val text: String = scala.io.Source.fromFile(file).mkString
val yaml = new Yaml(new Constructor(implicitly[ClassTag[T]].runtimeClass))
yaml.load(text).asInstanceOf[T]

I get the following error:

 org.yaml.snakeyaml.constructor.ConstructorException: Can't construct a java object for tag:yaml.org,2002:case_classes.Person; exception=java.lang.InstantiationException: NoSuchMethodException:case_classes.Person.<init>()

Please let me know if you see something wrong or if you can recommend a better approach.





Edit a List

I have a program in which I upload a DLL containing various types of objects. When uploaded, I create an instance of each type and save it into a Treeview (these objects may contain other objects inside). The purpose of the program is to edit these objects, so I have a propertyGrid which allows me to edit the selected object in the Treeview. This works perfectly fine for almost every object. I'm just having problems editing objects with properties whose types are List of xObjectType and this xObjectType has a yObjectType as property: For example, these classes are defined in the DLL, I have to edit FunctionCommand, however when I select the property Function in the propertyGrid a CollectionEditor pops up, this Collection Editor works fine when inner properties are of type int, string, byte[] etc. However I cannot edit properties which are more complex objects. In this case the RFunction property is disabled.

public partial class FunctionCommand
{
    /// <summary> Number of functions sent as part of the command</summary>
    public uint TotalNoOfFunctions { get; set; }

    /// <summary> Message structure for the function definition. Cloud shall always set this.</summary>
    public List<Function> Function { get; set; }

}

    public partial class Function
{
    public enum StoragePriorityENUM
    {
        LOW = 0,
        HIGH = 1,
    }

    /// <summary> Function id to uniquely identify a function</summary>
    public string FunctionId { get; set; }


    /// <summary> Set this ONLY for R function</summary>
    public RFunction RFunction { get; set; }
}

public partial class RFunction
{
    /// <summary> Diagnostics data for R function</summary>
    public DIAGData DiagData { get; set; }

    /// <summary>shall start the diagnostic process with a delay(minutes)</summary>
    public uint DelayTimeToStart { get; set; }

}

I can edit these type of objects correctly outside the CollectionEditor but not inside of it. Why does this specific property is not editable, How can I make to edit complex objects inside the CollectionEditor?





Set SOAPElement attribute from reflected object - JAVA

i'm trying to set an attribute value from a Object in a SOAPElement.

Field[] fields = object.getClass().getDeclaredFields();

for (Field field:fields) {
 try {

  field.setAccessible(true);
  String fieldName = field.getName();
  Object fieldValue = field.get(object);
  QName fieldQName = new QName(fieldName);

  SOAPElement element = soapBody.addChildElement();
  Element.addAttribute(fieldQName, fieldValue.toString());

  //For debugging
  System.out.println("Element" + fieldValue.toString());
 } catch (Exception e) {
   // Error handling
 }

}

The element is set with the right name, but the value is null for every element. When i print fieldValue.toString the values are correct.

What am i doing wrong?