C# Reflection: Instantiate an object with string class name - c#

my situation is the next: I'm working with Visual C# 2010 express developing a Windows Forms Application. When the user logins, dinamically build a menustrip with options loaded from a database table. In that table i save id, option name and Form Name.
So, suppose that in my project i have a Form named Contabilidad, it has Contabilidad.cs that is the main class , so if i wanna create a new form and show it i do this:
Contabilidad frmConta = new Contabilidad();
frmConta.Show();
But in this case, because the menu options are stored in database, in database i only have the string "Contabilidad". So, i want to use C# reflection to create a instance of Contabilidad or any other form only with class name in string format.
First i tried this:
Form frmConta= (Form)Activator.CreateInstance(null, "Contabilidad").Unwrap();
Because i read in a StackOverflow question that if i use null i'm referring to current assembly (my forms are all in the same project), but i get this message:
Could not load type 'Contabilidad' from assembly 'AccountingSA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
The class definition is the next:
namespace AccountingSA {
public partial class Contabilidad : Form
{
public Contabilidad()
{
InitializeComponent();
} ...
Also i tried this:
Assembly assembly = Assembly.Load("AccountingSA");
Type t = assembly.GetType("Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);
But i get ArgumentNullException with this message:
Value cannot be null. Parameter name: type
Because t variable is null.
What i'm do wrong? Thanks in advance.

Use the fully-qualified name of the type:
Type t = assembly.GetType("AccountingSA.Contabilidad");
From the documentation for Assembly.GetType(string):
name Type: System.String
The full name of the type.
[...] The name parameter includes the namespace but not the assembly.

You're trying to use the name of the class without specifying the namespace. This should be fine:
Assembly assembly = Assembly.Load("AccountingSA");
Type t = assembly.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);
Every version of GetType requires the fully-qualified type name; the benefit of using Assembly.GetType is that at least you don't need to also include the assembly name, but as documented you still need the namespace:
The name parameter includes the namespace but not the assembly.
Note that to diagnose something similar in the future, it would have been worth looking at the value of t after the second line - it will be null, which is why the third line threw an exception.

You should add the namespace:
assembly.GetType("AccountingSA.Contabilidad");

Try this
Form frmConta= (Form)Activator.CreateInstance(null, "AccountingSA.Contabilidad").Unwrap();

Try specifying your class this way:
ContabilidadNamespace.Contabilidad, ContabilidadAssembly

Its too late in the thread to answer, but the earlier answer, in current .NET framework (4.7), not working (The line Assembly assembly = Assembly.Load("AccountingSA"); always throws FileIOException). Currently, working code is (Use Type directly)
Type t = Type.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);
or other way using Assembly is
Assembly assembly = typeof(Form).Assembly;
Type t = assembly.GetType("AccountingSA.Contabilidad");
Form frmConta = (Form)Activator.CreateInstance(t);

Related

Retrieve <Version> tag written in csproj file from dll [duplicate]

I am trying to get the executing assembly version in C# 3.0 using the following code:
var assemblyFullName = Assembly.GetExecutingAssembly().FullName;
var version = assemblyFullName .Split(',')[1].Split('=')[1];
Is there another proper way of doing so?
Two options... regardless of application type you can always invoke:
Assembly.GetExecutingAssembly().GetName().Version
If a Windows Forms application, you can always access via application if looking specifically for product version.
Application.ProductVersion
Using GetExecutingAssembly for an assembly reference is not always an option. As such, I personally find it useful to create a static helper class in projects where I may need to reference the underlying assembly or assembly version:
// A sample assembly reference class that would exist in the `Core` project.
public static class CoreAssembly
{
public static readonly Assembly Reference = typeof(CoreAssembly).Assembly;
public static readonly Version Version = Reference.GetName().Version;
}
Then I can cleanly reference CoreAssembly.Version in my code as required.
In MSDN, Assembly.GetExecutingAssembly Method, is remark about method "getexecutingassembly", that for performance reasons, you should call this method only when you do not know at design time what assembly is currently executing.
The recommended way to retrieve an Assembly object that represents the current assembly is to use the Type.Assembly property of a type found in the assembly.
The following example illustrates:
using System;
using System.Reflection;
public class Example
{
public static void Main()
{
Console.WriteLine("The version of the currently executing assembly is: {0}",
typeof(Example).Assembly.GetName().Version);
}
}
/* This example produces output similar to the following:
The version of the currently executing assembly is: 1.1.0.0
Of course this is very similar to the answer with helper class "public static class CoreAssembly", but, if you know at least one type of executing assembly, it isn't mandatory to create a helper class, and it saves your time.
using System.Reflection;
{
string version = Assembly.GetEntryAssembly().GetName().Version.ToString();
}
Remarks from MSDN http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getentryassembly%28v=vs.110%29.aspx:
The GetEntryAssembly method can return null when a managed assembly has been loaded from an unmanaged application. For example, if an unmanaged application creates an instance of a COM component written in C#, a call to the GetEntryAssembly method from the C# component returns null, because the entry point for the process was unmanaged code rather than a managed assembly.
Product Version may be preferred if you're using versioning via GitVersion or other versioning software.
To get this from within your class library you can call System.Diagnostics.FileVersionInfo.ProductVersion:
using System.Diagnostics;
using System.Reflection;
//...
var assemblyLocation = Assembly.GetExecutingAssembly().Location;
var productVersion = FileVersionInfo.GetVersionInfo(assemblyLocation).ProductVersion
This should do:
Assembly assem = Assembly.GetExecutingAssembly();
AssemblyName aName = assem.GetName();
return aName.Version.ToString();
I finally settled on typeof(MyClass).GetTypeInfo().Assembly.GetName().Version for a netstandard1.6 app. All of the other proposed answers presented a partial solution. This is the only thing that got me exactly what I needed.
Sourced from a combination of places:
https://msdn.microsoft.com/en-us/library/x4cw969y(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/2exyydhb(v=vs.110).aspx

Call C# Method from C# Dll using Reflection

Good day,
I've got following problem. I'm working on my .dll library in C#, and I need to call a method of another C# project from the dll library.
For example I create a WPF project and I add reference of my .dll library.
Here is my WPF class (project):
using dllLibrary;
namespace Tester
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public void MyMethod()
{
MessageBox.Show("Test");
}
}
}
And here is my .dll project :
Type type = Type.GetType("Tester.MainWindow");
object instance = Activator.CreateInstance(type, null);
MethodInfo method = type.GetMethod("MyMethod");
return method.Invoke(instance, null);
By the way, it works when I call a method inside of the assembly
(of the dll project), but when I want to call a method outside of the dll project (Tester.MainWindow - the WPF project), it doesn't work.
Type.GetType without the full qualified name incl. assembly only works for types in mscorlib.dll. For all other types you have to pass the full qualified name of the type. So when you change the GetType call to something like this it will work:
Type.GetType("Tester.MainWindow, TestAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089);
You can load the assembly first using Assembly.LoadFile to get the full qualified name.

You must add a reference to assembly 'System, Version=1.0.5000.0

I'm trying to include a html to pdf converter in my C# program for windows mobile.
I found Pdfizer.
I added a refence to Pdfizer.dll and included it with using Pdfizer;
Also I added a reference to itextsharp that is required for Pdfizer.
Pdfizer is correctly added and I can use many of its functions and classes but I can't use HtmlToPdfConverter.Run()
My code:
FileStream filePDF;
filePDF = File.Create(path + ".pdf"); // path is string
html2pdf.Open(filePDF);
html2pdf.AddChapter(#"Chapter name");
html2pdf.Run(html); // html is a string that contains html code
html2pdf.Close();
Problem is in line html2pdf.Run(html); It says:
Error 1 The type 'System.Uri' is defined in an assembly that is not referenced.
You must add a reference to assembly 'System, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.
Definition of Run is
public void Run(string html);
public void Run(Uri uri);
I'm trying to use the Run(string html) option, but Uri is defined and visual studio says it is not referenced but yes it is.
I have using System; that contains Uri class, indeed I use it in other functions and works properly.
What is the problem? Should I add a reference to System, Version=1.0.5000.0? Where can I find It? Is there any way to tell Pdfizer Uri is in System.Uri?
Thanks
A public key token of b77a5c561934e089 indicates that you're referencing a desktop assembly, so my bet is that Pdfizer is built only for the desktop. There is no way to make that work in the COmpact Framework. If you can get the source, you can try to compile it for the CF, otehrwise you'll have to ask the owners if they have a CF version.

Why am I getting assembly version as 0.0.0.0? Will that make any issues if real DLL has some version number and using Type class to retrieve values?

I have a project named "Test.LiveModel" (Test.LiveModel.dll) and its version is 8.0.7.0 in my solution which contains 25 projects. I can see the information of Test.LiveModel in AssemblyInfo.cs. I have two category of objects named 'base class category' and 'user-defined class category' which are displaying in my application UI. I am displaying this through a property which is of class Type
Now I am considering one base class category object named "Server" and one user-defined class category object RoundedTree. When I set value as "Server" in Property in Grid after saving it when I restart my application I can see the saved value, but for "RoundedTree" which is not happening due to type becomes null. So I did a thorough analysis and came to know that issue is in ToType() method shown below
This is ToType() metho
For base class Server xmlSerializableType.Name, I am getting as Test.LiveModel.Server and AssemblyName I am getting as Test.LiveModel, Version=8.0.7.0, Culture=neutral, PublicKeyToken=23bd062a94e26d58 and type I am getting by using Type.GetType as type = {Name = "Server" FullName = "Test.LiveModel.Server"}
But for user defined class xmlSerializableType.Name I am getting as _Rounded_Tree. 'type' I am getting as null by using Type.GetType. AssemblyName I am getting as _Rounded_TreeTest-Machine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null, but even assembly.GetType I am getting as null. What is the reason behind it? Why am I getting assembly version 0.0.0.0? I mean full assembly _Rounded_TreeTest-Machine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null.
This is the method CreateType() which will create assembly and type as myTypeBuilder for userdefined class:
public Type CreateType()
{
// Create the assembly name by appending the machine name to the typename.
myAsmName.Name = this.TypeName + Environment.MachineName;
// Define assembly that can be executed but not saved
this.UserClassAssemblyBuilder = myDomain.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);
// Create dynamic module with symbol information
this.UserClassModuleBuilder = this.UserClassAssemblyBuilder.DefineDynamicModule("userdefinedmodule", true);
So here is my question: if real Dll has some version number, and user defined class assembly has version 0.0.0.0, is that the reason why I am getting type as null after using Type.GetType and assembly.GetType method?
Here are some suggestions which may solve the problems.
Define a assembly version
new AssemblyName(this.TypeName + Environment.MachineName)
{
Version = new Version("1.0.0.0")
};
Use full qualified names for the serialization
myObject.GetType().FullName

C# - Custom Attribute not found from GetCustomAttribute from Interface

I am attempting to setup a custom attribute like the following:
[AttributeUsageAttribute(AttributeTargets.Method)]
public sealed class AuthorizationAttribute : Attribute
{
public AuthorizationAttribute(bool required)
{
Required = required;
}
public bool Required;
}
In my service contract interface, I have a method like such:
[OperationContract]
[Authorization(true)]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "randommethod")]
ReturnObject RandomMethod();
When I do the following I see it in the list, but but the 'is' comparison, fails:
foreach(object attribute in methodInfo.GetCustomAttributes(true)) // Returns all 3 of my attributes.
if (attribute is AuthorizationAttribute) //Does not pass
I have tried to do the following that returns false:
Attribute.IsDefined(methodInfo, typeof(AuthorizationAttribute));
attribute.GetType().IsAssignableFrom(typeof(AuthorizationAttribute));
I have also done the following 2 things that returns null:
AuthorizationAttribute authAttribute = attribute as AuthorizationAttribute;
Attribute attribute = Attribute.GetCustomAttribute(methodInfo, typeof(AuthorizationAttribute));
I am not sure what I am doing wrong here. It seems like it should work, but I am sure I am making a simple mistake somewhere. Any insight?
Thanks for any assistance.
Edit:
I am not sure if it adds any meaning, but the AuthorizationAttribute declaration exists in a different project from my services project. The Service Contract interface exists in the same project as the AuthorizationAttribute.
I tried doing a cast and got the following exception:
[A]Lib.OAuth.AuthorizationAttribute cannot be cast to [B]Lib.OAuth.AuthorizationAttribute.
Type A originates from 'Lib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the
context 'LoadNeither' at location 'F:\RestServices\bin\Lib.dll'. Type B originates from 'Lib,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location
'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oauth_rest\951069b9
\9f7b77fe\assembly\dl3\54c48906\f928a6ad_01facb01\Lib.dll'.
Any ideas?
The exception contains the answer:
Type A originates...at location 'F:\RestServices\bin\Lib.dll'. Type B originates...at location
'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\oauth_rest\951069b9
\9f7b77fe\assembly\dl3\54c48906\f928a6ad_01facb01\Lib.dll'
The issue is that the Lib.OAuth.AuthorizationAttribute type which attributes your method is found in an assembly that is different than the assembly loaded at runtime when you try to cast.
Is it possible that one of your projects is using an old version of Lib.dll?
Thanks to Wesley's response, I was able to figure this out. It is more of a 'duh' moment than anything.
I was using some example code for reflection to load an assembly via the Assembly.LoadFile(...) method. The problem is that since my assembly was not registered with the GAC, it was reading the local copy on the IIS server and the comparison failed.
For reference, this was my solution:
Assembly.GetExecutingAssembly();
Once I did that, everything worked.

Categories

Resources