Create FileHelperEngine from Type variable - filehelpers

I am attempting to create an instance of FileHelperEngine<> using a generic type. For example this works for List
public static IList CreateList(Type type)
{
var genericListType = typeof(List<>).MakeGenericType(type);
return (IList)Activator.CreateInstance(genericListType);
}
Is it possible to do something similar for FileHelperEngine<>?
I tried
public static FileHelperEngine CreateFileHelperEngine(Type type)
{
var genericFileHelperEngineType = typeof (FileHelperEngine<>).MakeGenericType(type);
return (FileHelperEngine)Activator.CreateInstance(genericFileHelperEngineType);
}
And get this error
Unable to cast object of type 'FileHelpers.FileHelperEngine`1[NachaParser.Model.EntryDetail.PpdEntryModel]' to type 'FileHelpers.FileHelperEngine'.

This would not work because you are attempting to go from the generic engine to the standard engine. The generic engine does not inherit from the standard engine so you can't directly cast.
The following code should work for you:
public static FileHelperEngine<T> CreateFileHelperEngine<T>() where T : class
{
var genericFileHelperEngineType = typeof(FileHelperEngine<>).MakeGenericType(typeof(T));
return (FileHelperEngine<T>)Activator.CreateInstance(genericFileHelperEngineType);
}
The problem is that you need to have the type of T not as a Type variable but as as a passed generic argument. Unfortunately, the generic engine is based of EngineBase<T> with IFileHelperEngine<T> as an interface it implements so you can never get a FileHelperEngine<T> to a FileHelperEngine.
Your only other option is to use:
public static FileHelperEngine CreateFileHelperEngine(Type type)
{
if (!type.IsClass)
throw new InvalidCastException("Cannot use '" + type.FullName + "' as it is not a class");
return new FileHelperEngine(type);
}

Related

Issue accessing fields in generic base class using Fody

Consider the following test code structure:
class TestClass<T>
{
public object TestObject;
}
class TestClass2<T> :TestClass<T>
{
public int TestMethod()
{}
}
When I add Instruction.Create(OpCodes.Ldfld, TestObjectField) to TestMethod, I get the following result:
ldfld class Object TestNamespace.TestClass`1::TestObject
This causes an issue in the secure plugin system of Dynamics CRM (more information could be found here). However, when I add TestObject = new object() to TestMethod, I get the following result, which runs fine:
ldfld class Object class TestNamespace.TestClass`1<!T>::TestObject
This only happens when the object I am trying to access is in a generic base class. Is there a way that I can simulate the desired result from within Fody please?
UPDATE:
I managed to partially solve the issue by using the following lines:
var testObjectFieldRef = testObjectFieldDefinition?.Resolve().GetGeneric();
var testClassTypeRef = testObjectFieldRef?.DeclaringType.Resolve().GetGeneric();
if (testClassTypeRef != null)
{
testObjectFieldRef.DeclaringType = testClassTypeRef;
}
It seems that by default the ModuleDefinition does not provide a generic type/field definition; so it has to be done explicitly. In addition, the types of the generic parameters are not specified, so it's still an issue.
I managed to solve this issue by using the following code (reference):
var genericBaseType = (GenericInstanceType) testClassTypeRef.BaseType;
var genericArgs = genericBaseType .GenericArguments;
var fullBaseTypedName = genericBaseType.ElementType.MakeGenericInstanceType(genericArgs.ToArray()).FullName
Which returns ldfld class Object class TestNamespace.TestClass`1<!T>::TestObject as required. It will also fill in the type of the type parameter (in place of <!T>) if given in the derived class.

How to write a List of a specific type using kryo serializer

I am trying to write a List of a specific type using Kryo serializer but I am getting errors when I try to read/write it. I am using source provided by apache spark for KryoRegistrator
List I am trying to write is of type List<A> which could be an ArrayList or any other type of list
Code
Class FakeRegsitrator implements KryoRegistrator{
#Override
public void registerClasses(Kryo kryo) {
CollectionSerializer listSerializer = new CollectionSerializer();
listSerializer.setElementClass(A.class, kryo.getSerializer(A.class));
listSerializer.setElementsCanBeNull(false);
kryo.register(A.class, new Serializer<A>(true, true) {
public void write(Kryo kryo, Output output, A a) {
output.writeLong(a.getFieldA)
output.WriteString(a.getFieldB)
}
public A read(Kryo kryo, Input input, Class type) {
return new A(input.readLong(), input.readString())
}
}
}
What am I missing here?
I was able to get it working by registering Arraylist.class
code :
kryo.register(ArrayList.class);
in read method use
kryo.readObject(input, ArrayList.class);
in write method use
kryo.writeObject(output, entry.getArchivePortions());

VB.Net Merge property class from more than one web references

I have project that need to reference to some web service, just say my reference is
service1Facade and service2Facade
both of them contain class name objectA
i must load objectA from service1Facade and use it as parameter in service2Facade.
but i got error
"value of type service1Facade.objectA cannot be converted to service2Facade.objectA"
how can i convert these object ?
what i have try but still not work:
group all reference into same folder, but .NET change its name into
objectA and objectA1
I copy every property of the property inside objectA, but still not working.
The functionality that is responsible for generating proxy classes based on your WSDL specification doesn't know (and it shouldn't know) that both your services use the same underlying type for objectA, and as I mentioned, no assumptions can be made regarding this since web services are meant to be decoupled from each other (from the consumer point of view).
I'd say your best option is to have your own proxy class (let's say ServiceProxyDTO) that can be used in both service #1 and #2. Something along the lines of:
public class ServiceProxyDTO
{
// Define properties from "objectA"
public ServiceProxyDTO() { }
public ServiceProxyDTO(service1Facade.ObjectA copyFrom)
{
// Copy state from "copyFrom"
}
public ServiceProxyDTO(service2Facade.ObjectA copyFrom)
{
// Copy state from "copyFrom"
}
public static implicit operator service1Facade.ObjectA(ServiceProxyDTO dto)
{
return new service1Facade.ObjectA() { /* Copy state back */ };
}
public static implicit operator service2Facade.ObjectA(ServiceProxyDTO dto)
{
return new service2Facade.ObjectA() { /* Copy state back */ };
}
public static implicit operator ServiceProxyDTO(service1Facade.ObjectA obj)
{
return new ServiceProxyDTO(obj);
}
public static implicit operator ServiceProxyDTO(service2Facade.ObjectA obj)
{
return new ServiceProxyDTO(obj);
}
}
With this code you can instantiate ServiceProxyDTO and pass it as parameter to both service #1 and #2 (as well as get the return values from both of these services).
Hope this helps.

PexChoose non generic methods

Is there any way to specify the return type for PexChoose at runtime? For example PexChoose.Value(name, Type)?
This would be useful to make general models that generate values of different types depending on runtime contraints.
You could build your own helper class which will call the generic version via reflection.
For instance, to create a non-generic version of PexChoose.Value(string name)
public static class MyPexChoose
{
public static object Value(Type myType, string name)
{
// Find the PexChoose.Value() method which has a single string parameter
MethodInfo method = typeof(PexChoose).GetMethod("Value", new Type[1] {typeof(string)});
// Make and invoke the generic version of it
MethodInfo generic = method.MakeGenericMethod(myType);
return generic.Invoke(typeof(PexChoose), new object[1] { name });
}
}
Then the call
MyPexChoose(typeof(DateTime), "MyChosen");
is equivalent to
PexChoose<DateTime>("MyChosen");

One method to read parameters, properties and return types at runtime using C#

With continutation to my earlier thread Using reflection read properties of an object containing array of another object. I am hoping to make this wonderful method from EvgK a generic method that can be used in multiple places in my code base.
public static void GetMyProperties(object obj)
{
List<MyPropertyInfo> oMyProp = new List<MyPropertyInfo>();
foreach (PropertyInfo pinfo in obj.GetType().GetProperties())
{
if (!Helper.IsCustomType(pinfo.PropertyType))
{
//add properties - name, value, type to the list
}
else
{
var getMethod = pinfo.GetGetMethod();
if (getMethod.ReturnType.IsArray)
{
var arrayObject = getMethod.Invoke(obj, null);
foreach (object element in (Array)arrayObject)
{
foreach (PropertyInfo arrayObjPinfo in element.GetType().GetProperties())
{
//add properties - name, value, type to the list
}
}
}
else
{
List<MyPropertyInfo> oTempMyProp = GetMyProperties(prop.GetValue(obj, null));
oMyProp.AddRange(oTempMyProp);
}
}
}
}
Again, I am trying to read a method passed by the user. I list the parameters, their properties and values. Once user provides the input values, I call the method dynamically to get the result object. The result is passed to GetMyProperties() method and the method list all the properties (to n level) - name, value and type.
Currently, I have two methods (definations below):
public List<MyPropertyInfo> GetMyProperties(Type type);
public List<MyPropertyInfo> GetMyProperties(object obj);
I use the first one to show the list of all the parameters of the selected method along with it's properties - name, value and type.
MethodInfo members = type.GetMethod(this.MethodName);
ParameterInfo[] parameters = members.GetParameters();
List<MyPropertyInfo> oMyProp = new List<MyPropertyInfo>();
foreach (var parameter in parameters)
{
oMyProp = GetMyProperties(parameter.ParameterType);
}
..creating the list of my properties so that user can input the params. I pass ParameterType and GetProperties method checks if it is custom type or not. If custom type then it calls itself with the type recursively to build a list that I bind to a grid for input.
The second method GetMyProperties(object obj) is used to list the return object. Since I don't know the return type of the selected method at compile time so using object type. I want to know if I can modify the second method somehow to use it for reading the parameters, properties and return types? Instead of having separate methods? Trying to reuse the code.
I'm not sure I understand you correctly, but if you want to combine two methods in one, you can pass object in both cases, but check if object is Type or not and provide different logic for that cases:
public static void GetMyProperties(object obj)
{
if (obj is Type)
{
Type type = obj as Type;
... here is the first method logic ...
}
else
{
... here is the second method logic ...
}
}