How can I create variable controls at runtime? - c#

I'm trying to create controls at runtime using Reflection.
In my case, I get a string like Label or Button and I would like to create a object Label or Button of it.
Assembly WinFormasm = Assembly.Load("System.Windows.Forms,Version=2.0.000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Control label = (Control)Activator.CreateInstance(WinFormasm.GetType("System.Windows.Forms."+type));
When I execute this, I get the error:
File or assembly name 'System.Windows.Forms,Version=2.0.000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089', or one of its dependencies, was not found.
I don't realy know what is wrong there. I have also tried:
try
{
Type cntrl = Type.GetType("System.Windows.Forms.Button,System.Windows.Forms, Culture=neutral, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089", true);
label1.Text += cntrl.ToString() + " ";
}
catch(Exception e)
{
label1.Text += e.ToString() + " ";
}
Trying this, I got an execution error: he can't create the type and returns null. If I change the gettype string into System.Int32, it works.
How can I create a control item using a string?

What's wrong with the following?
Button cntrl = new Button();
If you're hardcoding the values why do you need to use reflection?

Your version number is wrong for System.Windows.Forms:
var assembly = Assembly.Load("System.Windows.Forms, version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Then to create the desired control type, just specify the type name:
var type = "Button";
var control = (Control)Activator.CreateInstance(assembly.GetType("System.Windows.Forms." + type));

to create the controls from string
you need to use Activator class
check this link

http://bytes.com/topic/c-sharp/answers/236152-how-create-control-instance-dynamicly-text had a quite intesting idea to solve the problem with a little fix it worked for me.
I get the type of form (controls are standing in a form right) from that type I get the assembly.
From the assembly I get the object by calling the gettype function with the parameters of the type of control I would like.
Finally I cast it to a control type.
private Control createcontrol(string type)
{
Type typen = typeof(Form);
Assembly assem = typen.Assembly;
//Assembly assem = Assembly.LoadFrom(typeof(Form).ToString());
Type controlType = assem.GetType("System.Windows.Forms."+type); // GetType(controlType);
object obj = Activator.CreateInstance(controlType);
Control control = (Control)obj;
return control;
}
Thanks for the help folks!

string ControlType = "TextBox";
Assembly FormAssembly = Assembly.GetAssembly(typeof(Form));
Control MyControl = (Control)FormAssembly.CreateInstance("System.Windows.Forms." + ControlType);
Just change ControlType value.

Related

Azure Redis Exception while executing function: MyFunction -> Unable to find assembly 'MySolution.MyProject.MyService

While using CachingFramework.Redis I am trying to insert an object into a key, field hash...
enter code here
var map = new MyMapping
{
DataSourceId = source.DataSourceId,
ExternalId = source.ExternalId,
StoreId = source.StoreId ?? 0,
LastConnection = source.LastConnection,
ApiKey = source.ApiKey
};
Context.Cache.SetHashed("MyRedisKey", "MyFieldKey", map, TimeSpan.FromHours(1));
But, when I try to get the hashed value back out...
var MyCachedValue = Context.Cache.GetHashed<MyMapping>(("MyRedisKey", "MyFieldKey");
I get the error...
"Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: MyFunction ---> System.Runtime.Serialization.SerializationException : Unable to find assembly 'MySolution.MyProject.MyService, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.FunctionInvocationFilterInvoker.InvokeAsync(Object instance,Object[] arguments)\r\n at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,ParameterHelper parameterHelper,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)\r\n ....
Are you setting and retrieving the value in different assemblies? It looks like that might be the case.
In that event, you need your Map to be defined in a shared assembly that is referenced by both the project that sets the value as well as the project that gets the value.
GetterProject
SetterProject
SharedModels
Both 1 and 2 should reference 3, and that is where you should define the objects stored in your cache.

Get text property of all forms in an assembly via reflection

I'm trying to iterate over all assemblies in my solution, get all forms and retrieve the text property of each form but I don't really know how to get the value. Here is my code:
Type formType = typeof(Form);
var assemblies =
AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var types = assembly.GetTypes();
foreach (var type in types)
{
if (formType.IsAssignableFrom(type))
{
var properties = type.GetProperties().Where(x => x.Name == "Text");
}
}
}
I'm not able to retrieve the concrete value of the form text property. I also
tried
var property = type.GetProperty("Text").GetValue(???, null);
but don't know how to get the current class. Any ideas? Thank you!
EDIT: i also tried
var frm = (Form)Activator.CreateInstance(type)
but if the form has no parameterless constructor this will fail.
You can try to iterate over Application.OpenForms collection. This will get you all opened forms owned by the application.
MSDN
If you need only references to open forms, you can use Application.OpenForms.
Otherwise you need to have some list of all form references.

Why would Type.GetType return null with telerik types in sitefinity?

I have set up a widget for the backend of my Sitefinity site that has three textboxes and a button. The goal is to create a new column in the database:
protected void btnAddClick(object sender, EventArgs e)
{
Type TelerikType = Type.GetType(txtTelType.Text);
Type ColumnType = Type.GetType(txtColType.Text);
string error = "";
if (TelerikType == null)
{
error = "Telerik Type is invalid";
}
if (ColumnType == null)
{
error = "Column Type is invalid";
}
if (error.Length == 0)
{
App.WorkWith()
.DynamicData()
.Type(TelerikType)
.Field()
.TryCreateNew(txtName.Text, ColumnType)
.SaveChanges(true);
error = "Added column successfully";
txtColType.Text = txtName.Text = txtTelType.Text = "";
}
literalErrorText.Text = string.Format(literalErrorText.Text, error);
}
I am having two problems:
When I enter Telerik.Sitefinity.Pages.Model.PageNode into the textbox, Type.GetType(txtTelType.Text) is returning null.
If I replace that portion with typeof(PageNode) I get "Specified type 'Telerik.Sitefinity.Pages.Model.PageNode' is not a dynamic type."
I'm hoping somebody might have some insight as to why these things wouldn't work correctly, or possibly a better way to approach this issue? For reference, my goal (at least for now) is to add a dynamic column that references PageNode so that I can specify a ShowInLeftNavigation boolean and a ShowInRightNavigation boolean. Thank you for any help you can provide.
Read the docs carefully here:
typeName Type: System.String
The assembly-qualified name of the type
to get. See AssemblyQualifiedName. If the type is in the currently
executing assembly or in Mscorlib.dll, it is sufficient to supply the
type name qualified by its namespace.
So if the type is not one of the base .Net types, or in the currently executing assembly, you have to tell GetType what assembly to look in as well.
I don't know what assembly the Telerik control are in, but it looks like you will have to add the assembly to the type name, something linke this:
TopNamespace.SubNameSpace.ContainingClass, MyAssembly,
Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089
Follow the link for "AssemblyQualifiedName" above to get all the gory details of the syntax.
Type.GetType doesn't that check for Object type
for example System.String ect... can you try replacing the = null with
if (TelerikType.Equals(null))

How can I dynamically call a method using Namespace.Class in C#?

I have an event like this:
private void btnStartAnalysis_Click(object sender, EventArgs e)
{
SqlConnectionStringBuilder objConnectionString = new SqlConnectionStringBuilder();
objConnectionString.DataSource = txtHost.Text;
objConnectionString.UserID = txtUsername.Text;
objConnectionString.Password = txtPassword.Text;
objConnectionString.InitialCatalog = Convert.ToString(cmbDatabases.SelectedValue);
string[] arrArgs = { objConnectionString.ConnectionString };
//Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.
string assemblyName = cmbOperations.SelectedValue.ToString();
Assembly assembly = Assembly.LoadFrom(assemblyName);
Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
IMFDBAnalyserPlugin analyser = (IMFDBAnalyserPlugin) Activator.CreateInstance(localType);
string response = analyser.RunAnalysis(objConnectionString.ConnectionString);
//show the response of the the function call
txtPluginResponse.Text = response;
}
I want this line to be dynamic:
Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
where PrimaryKeyChecker is a namespace and another PrimaryKeyChecker is the class.
But I want to create other namespaces and classes, so is there any way to call them dynamically and load them in the combobox like this.
public void SetOperationDropDown()
{
cmbOperations.DataSource = PluginManager.GetAllPlugins();
if(cmbOperations.Items.Count > 0)
{
cmbOperations.SelectedItem = cmbOperations.Items[0];
}
}
You've almost answered your own question! Assuming you have a list of plugins, configured in a config file or whatnot, then your PluginManager can load up the Types from the assembly using code similar to:
Type analyserType = typeof(IMFDBAnalyserPlugin);
foreach(Type t in assembly.GetTypes()) {
if(t.IsSubtypeOf(analyserType) {
plugins.Add((IMFDBAnalyserPlugin) Activator.CreateInstance(t));
}
}
If you do not have a list of plugins, then you can either scan a directory and do the same thing as above. You could also consider using a plugin framework architecture like MEF and it does a lot of that work for you and discovers the assemblies and plugins at runtime.
I think the answer of Tom can help you populate a list of plugins. Bind them to the combobox where you put the text / description to the Type name and bind the value of combo-items to the actual Type declaration. And you asked for the event to be "Dynamic"...Do you probably mean generic??? Then i would advice to refactor the code in the click_event to a private method, to be able to call it from other "places" as well. Then in the click_event you retrieve the selected Plugin Type from the currently selected item a provide this in the generic function call to RunAnalysis like this:
private void btnStartAnalysis_Click(object sender, EventArgs e)
{
if(cmbOperations.SelectedItem != null)
RunAnalysis<cmbOperations.SelectedItem.Value>();
}
private void RunAnalysis<T>()
{
//Checks for the selectedItem in the cmbOpearions dropdown and make call to appropriate functions.
//string assemblyName = cmbOperations.SelectedValue.ToString();
//Assembly assembly = Assembly.LoadFrom(assemblyName);
//Type localType = assembly.GetType("PrimaryKeyChecker.PrimaryKeyChecker");
IMFDBAnalyserPlugin analyser =
(IMFDBAnalyserPlugin) Activator.CreateInstance(T);
string response = analyser.RunAnalysis(objConnectionString.ConnectionString);
//show the response of the the function call
txtPluginResponse.Text = response;
}
Another way could be to just use a parameter for the Type currently selected. Hope this helps you out or to bring you to new ideas towards a solution.

NullReference Exception unhandled. C# Reflection

ControlType = "System.Windows.Forms.WindowsFormsApplication1." + "PictureBox1";
System.Reflection.Assembly asm;
asm = typeof(Form).Assembly;
ControlObject = (System.Windows.Forms.Control)asm.CreateInstance(ControlType);
ControlObject.Name = ControlName;
The next code generated following exception for me:
ControlObject.Name = ControlName;
NullReferenceException was unhandle
Object reference not set to an instance of an object.
Assembly.CreateInstance is expecting a type name and you appear to be passing it the name of an instance of a type (namely, a PictureBox named PictureBox1.). Therefore, ControlObject is null and thus ControlObject.Name will throw a NullReferenceException.
It's not clear what you're trying to do, but that is why you are encountering the problem that you are. If you're trying to create a new instance of PictureBox I don't see why you don't just say new PictureBox(); this class has a public parameterless constructor. Alternatively, if you insist on reflection, you could say
controlType = PictureBox1.GetType();
controlObject = Activator.CreateInstance<Control>(controlType);
We could help more if we knew what you were trying to do instead of just throwing code that doesn't work at us and expecting us to solve world hunger.
Additionally,
ControlType = "System.Windows.Forms.WindowsFormsApplication1." + "PictureBox1";
Please rename this variable to controlType. You should use camel case for variable names.
Why do you have your application class WindowsFormsApplication1 living in the system namespace System.Windows.Forms? Don't do this.
You're probably trying to write
ControlObject = new PictureBox();
Looks like CreateInstance returns null, which means the type wasn't found in the assembly. Is PictureBox1 a type or an object?
Surly your application is not in System.Windows.Forms namespace
"System.Windows.Forms.WindowsFormsApplication1." + "PictureBox1"
Try:
ControlObject = (System.Windows.Forms.Control)asm.CreateInstance(typeof(PictureBox));
or just
ControlObject = new PictureBox();
to create a new instance of control.
Or maybe you want to find an existing PictureBox control on your form?
It means that asm.CreateInstance(ControlType); is returning null.
So, ControlType has a wrong value. It is supposed to recieve as parameter a type http://msdn.microsoft.com/en-us/library/dex1ss7c.aspx and it seems that you are sending an instance PictureBox1.
It should be ControlType = "System.Windows.Forms.PictureBox";

Categories