VB to C# Translation - c#

In VB (ASP.NET)
Application("myapp")= Server.CreateObject("APP.Engine")
aa = Application("myapp").myMethod(2)
works.
In C# I tried
Application["myapp"]= Server.CreateObject("APP.Engine")
but
Application["myapp"].myMethod(2)
fails with
'object' does not contain a definition for 'myMethod'
How can I expose the public interface in C#?

If you have access to the defining type (i.e. not a raw COM object), you can simply cast:
((APP.Engine)Application["myapp"]).myMethod(2);
If you are using c# 4.0, you can do:
dymamic myApp = Application["myapp"];
myApp.myMethod(2);
Otherwise you will have to use dynamic method invocation using reflection and Type.InvokeMember(...)

You need to cast to the correct class first, like:
((APP.Engine)Application["myapp"]).myMethod(2)

Cast the result of Application["myapp"] to the correct type, like so:
((APP.Engine)Application["myapp"]).myMethod(2);
Other options include creating a local reference and using that instead.

This basically happens as C# is strongly typed language. When you call Application you are actually calling a collection of type Object. The collection is actually an array of Object. We take it as object because it will enable you to store almost anything to the collection.
Now Application["myapp"] will eventually return an object of System.Object type.
So you need to typecast the object to your type.
App.Engine obj = Application["myapp"] as App.Engine;
if(obj != null)
obj.myMethod(2);
The object obj is a reference to the actual type and the compiler will not throw any exception if you call myMethod(2).

Just remember one thing while converting code from VB to C# is, C# is the strongly typed language and before you access any type, you will need to convert it. However same wasn't required in VB.
So for this example you would need to use App.Engine for type conversion.
((APP.Engine)Application["myapp"]).myMethod(2)

Related

not able to create object with Activator.CreateInstance

I am trying to load the old version of farpoint dll in my project by using below code
System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(#"FarPoint.Web.Spread.dll");
System.Type MyDLLFormType = assembly.GetType("FarPoint.Web.Spread.FpSpread");
var c = Activator.CreateInstance(MyDLLFormType);
The problem is after the instance is created, all the available methods of farpoint are not available
[ for example - if i create the object directly the methods like saveExcel or savechanges are available with the instance]
FpSpread fpProxyObject = new FpSpread();
fpProxyObject.SaveExcel();
They are available, just not at compile time. Activator.CreateInstance() returns an object. You could of course cast the object:
var c = Activator.CreateInstance(...)
FpSpread fpProxyObject = (FpSpread)c;
But that would probably beat the whole purpose of using reflection to create the instance.
You can access all members of the result object by using reflection, ie:
MethodInfo saveExcelMethod = c.GetType().GetMethod("SaveExcel");
if (saveExcelMethod == null) throw new ApplicationException("Incorrect version of FarPoint");
saveExcelMethod.Invoke(c);
Intellisense is not working, because, as said #C.Evenhuis, Activator.CreateInstance returns object, so you should cast it to appropriate type.
If type is not known at compile time, but you have access to a code-base, you could try to add interface for it, and implement it by your class. Then cast object to that interface and use it. (I don't know your purpose, but interface could be treated as a contract for all the types, that you will load dynamically).
If type is not known at compile time and you have no access to a code-base, you could use reflection for method invocation or use dynamic instead.
dynamic c = Activator.CreateInstance(MyDLLFormType);
c.SaveExcel(); // this method invocation will be bound in runtime.
By the way be carefull, while using Assembly.LoadFile. You may get more details from this article.

Trying to get a referenced vb.net dll to showdialog in c#

I've got a legacy vb.net dll referenced in my c# project.
calling the various methods no problem, but I need to be able to display a form from the dll, so users can pick the right line from a database response.
Assembly assembly = Assembly.LoadFile("FMSValidation.dll");
produces no error, but
Type type = assembly.GetType (FMSValidation.CreditorDetails );
tells me 'CreditorDetails' is a type, which is not valid in the context.
assembly.GetType does not accept an actual type. It accepts a string:
Type type = assembly.GetType("FMSValidation.CreditorDetails");
It wouldn't make sense for assembly.GetType to be able to take a type, since at that point you already have a type.
Once you have a type, you can create an instance of it with the activator class:
var form = (System.Windows.Forms.Form)Activator.CreateInstance(type);
form.ShowDialog();
If CreditorDetails requires any constructor arguments, use an overload of CreateInstance that accepts the array of arguments.
It seems like the compiler knows FMSValidation.CreditorDetails is a type - so I wonder why you are dynamically loading the assembly and trying to use GetType at all. You should just be able to add a reference to the assembly and use its types like you would any other, like new FMSValidation.CreditorDetails().
FMSValidation.CreditorDetails is a type, but it is not an actual Type object. If you want an actual type object, and you can write the name of the type in your source code (ie. it's not in a string variable or something) then you would use typeof(FMSValidation.CreditorDetails) instead of assembly.GetType.

How do create a Generic Object using Reflection

First let me say, that what I want to do is get the value of a property in a generic class that may be overriden by class that inherits from it. Think of it in the base class as a default value, that the inheritor of the class can override to set their own Default value.
I have tried to use reflection directly on the type, using the System.Reflection.FieldInfo.GetValue but this does not work for classes with generic types. So I think that I need to instantiate the class to be able to see what the value is.
The "types" I have I retrieved by reading the Dlls in the bin and using Reflection to find the types that inherit from my interface.
I am using .NET 4.5
here is documentation that seems like it explains exactly what I need to do
http://msdn.microsoft.com/en-us/library/b8ytshk6.aspx
In this documentation the only difference I can see is how we got our types, I looked in the bin for types and they simply called typeof(), Since types are so complex it seems this may be a likely mis-match but I cannot see what is missing(if anything)
foreach (var item in types)
{
var ts = item.GetField("DefaultTimeToExpire");
Type[] typeArguments = item.GetGenericArguments();
if (ts != null)
{
var t = item.MakeGenericType(typeArguments);
var obj = Activator.CreateInstance(t);
var timespan = obj.DefaultTimeToExpire;
subscriberInfos.Add(new Tuple<string, Type, TimeSpan>(item.Name, item, timespan));
}
}
I am calling GetField to look for Items that have a field "DefaultTimeToExpire" so far this part works well to find the type I need.
Next I call GetGenericArguments which returns an expected array of the type Arguments.
then I call MakeGenericType
and finally Create instance wich gives me the error message
"Cannot create an instance of BusinessLogic.TestSubscriberXXX`1[Message] because Type.ContainsGenericParameters is true."
This looks like exactly what I am supposed to do.
Thanks
In order to instantiate a generic type, you need to know the actual values (types) that should be substituted for its type parameters. The GetGenericArguments() method, being a form of reflection, only gives you the type arguments, not their actual values. The values are up to you... that is the entire point of generics.
If item is a type like List<T> then item.GetGenericArguments() will return an array containing a fake "type" representing the type parameter T (with its IsGenericParameter property set to true). Therefore, passing that parameter type back into item.MakeGenericType() will simply create another open generic type equivalent to the original. To close the generic type so that it can be instantiated you need to provide an actual (non-parameter) type argument, such as int.
For example, typeof(List<>).MakeGenericType(typeof(int)) will return typeof(List<int>), while typeof(List<>).MakeGenericType(typeof(List<>).GetGenericArguments()) will simply return typeof(List<>) again. This is what is happening in your code.
I'm sorry if that is a bit opaque, I don't know how else to explain it. The bottom line is that a type like List<T> is only useful if you have a type you want to substitute in place of T.

How to create an instance of value types using reflection

I want to create an instance of value types like System.String, System.Boolean, System.Int32, etc. I get qualified names of types like System.String or MyNamespace.Employee and I have to create an instance and return back. I use Activator.CreateInstance and FormatterServices.GetUninitializedObject to create instances. But it fails in case of value types. I cannot hard code the logic in case of value types. I need a generic way of creating instances of both value types and reference types.
What exactly is it you are trying to do? FormatterServices.GetUninitializedObject is used mainly by serialization code; outside of that you shouldn't really use it. It sounds like you might just need something like TypeConverter, i.e. (for these types)
TypeConverter tc = TypeDescriptor.GetConverter(someType);
object obj = tc.ConvertFromString(s);
What exactly is failing? I tried the following code to see if there is a problem with value types:
var instance = Activator.CreateInstance(typeof(Int32));
It gives me an Int32 instance set to 0.
Where exactly is your code failing? Otherwise I would say the problem lies with the way you are loading the type, not the way you are creating the instance.
For BCL Value Types (and when using Strings to describe types) ensure you are not using C# keywords and ensure the Type is fully qualified with namespace. For example, C# int is successfully created this way with Activator.CreateInstance(..)
object num = Activator.CreateInstance(Type.GetType("System.Int32"));
You will get failed attempts if you try to use language-specific aliases like "int" or short forms like "Int32".
This works for me:
int x = (int)Activator.CreateInstance(typeof (Int32), true);

Why this is not possible in C# Generics?

A colleague pointed me to a strange case in C# (not so sure if this actually strange though).
Suppose you have a class Employee. If you want to create a Generic List<> of type Employee, you can simply do:
List<Employee> x = new List<Employee>;
I understand that I need to pass the Employee type to the Generic list so that it knows the required type information about Employee and generates methods that return and accept parameters that are compatible with Employee.
Now my question is, why isn't it possible to do the following?
Employee x = new Employee();
List<typeof(x)> list = new List<typeof(x)>();
Shouldn't this suffice the information required for List<> to know, in order to create a list? In other words, the type of x which is the type of Employee is now passed as a generic type parameter to List<>, which (as I used to believe) is the same as passing list the type name (in this case Employee).
I know that something like this is available in Java (using the .class) keyword on a variable.
I'm sure I AM missing something, so please, enlight me guys!
No, the equivalent of that isn't available in Java. You can't use "x.class" to get at the declared type of a variable.
Moreover, typeof(x) doesn't work in C# either to get the type of a variable - it returns a Type reference for the type name, e.g. typeof(string) will return a reference to the Type object associated with the System.String type. That's equivalent to using String.class in Java. (Note that again, that's applying .class to a type name, not a variable name.)
Java generics don't support anything like your final statement either. If you believe they do, please give a sample :)
What you can do in C# is use type inference to do what you want:
public static List<T> CreateListForSampleType<T>(T sample)
{
return new List<T>();
}
...
Employee x = new Employee();
var list = CreateListForSampleType(x);
Note that there's no reason why C# couldn't be extended to allow something like typeof(variablename) or List<typeof(variablename)> - it's all compile-time type information, after all. However, I can't see that it would meet the team's requirements for usefulness... there are other far more useful features I'd like to see first :)
The reason for this is that typeof() returns a type object, while you need a type name to initialize a list at compile-time.
One part of the answer is that the type of x is not available at compile time, i.e. it might be created using something like this:
Employee x = EmployeeFactory.NewEmployee("John Doe"); // Returns TraineeEmployee, Employee or ManagementEmployee;
List<typeof(x)> l = new List<typeof(x)> l(); // What type is it?
You can however create a List of a base class of what you want to store in the list (or even a List of "object"s).
typeof is used with class names. Use GetType() on an object, but only at runtime...
What you are missing - imho - is the difference between a static type reference at compile-time and a dinamyc type reference (via an instance of System.Type) at run-time.
typeof() and .GetType() give you the latter. (for types and instances, respectively)
I hope it makes clear.
Jon Skeet's code above is cool.
Can't find a reason to create an empty list since C# 3.0.
I generally create list instances only with a ToList method from an IEnumerable, which is in turn generated using a yield return, Concat(), Repeat(), Where() etc.
var list = CreateEmployees().ToList();
,
public IEnumerable<Employee> CreateEmployees()
{
yield return new Employee("Foo");
yield return new Employee("Bar");
}

Categories