How can I get all the controls in a namespace? For example, I want to get the controls in System.Windows.Forms: TextBox, ComboBox etc.
The notion of a control in a namespace is a bit unclear. You could use reflection to get classes in an assembly in a given namespace which derive from a particular base type. For example:
class Program
{
static void Main()
{
var controlType = typeof(Control);
var controls = controlType
.Assembly
.GetTypes()
.Where(t => controlType.IsAssignableFrom(t) &&
t.Namespace == "System.Windows.Forms"
);
foreach (var control in controls)
{
Console.WriteLine(control);
}
}
}
this will return all classes in a specified namespace :
string #namespace = "System.Windows.Forms";
var items = (from t in Assembly.Load("System.Windows.Forms").GetTypes()
where t.IsClass && t.Namespace == #namespace
&& t.IsAssignableFrom(typeof(Control))
select t).ToList();
Your form object has a Controls member, which is of type ControlCollection. It is essentially a list (with some other interfaces under the hood) of all of the controls.
EDIT: As per your comment, you need to cast the control back into a textbox. First you must identify it as a control.
foreach (var control in controls)
{
if(control is TextBox)
{
(control as TextBox).Text = "Or whatever you need to do";
}
}
Related
I have a base form (BaseForm) which needs to be inherited from all the forms in the project. Some of them inherit it, others not. How can I get a list of all those forms who currently don't inherit it because we have a lot of forms and will be time consuming to go and check if each one of them inherits this form? Maybe some reflection ?
Use the check Type.IsSubclassOf().
Assembly assembly = Assembly.GetExecutingAssembly();
Type baseType = typeof(BaseForm);
foreach (Type type in assembly.GetTypes().Where(t => (t.FullName.Contains("Form") && (t != baseType))))
{
if (type.IsSubclassOf(typeof(BaseForm)))
Console.WriteLine("{0} is subclass of {1}", type, baseType);
}
Type formType = typeof(Form);
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
if (formType.IsAssignableFrom(type))
{
// print the list of forms
}
My UI is build with lots of user controls that are translatable. Some controls in the usercontrols shouldn't be translated and I want to tag them as such with a [DoNotTranslate]` custom attribute.
in my userControl.designer.cs file
[DoNotTranslate]
private DevExpress.XtraEditors.LabelControl maxLabel;
[DoNotTranslate]
private DevExpress.XtraEditors.LabelControl valueLabel;
//all other controls
The translation function expects a (user)control and then goes through all the child control.Controls to make sure all controls are translated without the need to call the translation function on every single control.
Is it possible to find out if a control has my custom attribute set? The problem is that I don't see how I can get the attribute information in the translation function when i go through all the Controls.
Any advice is greatly appreciated,
Thanks
EDIT: I see now from the code you posted that the attribute is on a property of the control, not on the class defining the control itself. You can try like this:
public IEnumerable<PropertyInfo> GetNonTranslatableProperties(WebControl control)
{
foreach (PropertyInfo property in control.GetType().GetProperties())
{
if(
property
.GetCustomAttributes(true)
.Count(item => item is DoNotTranslateAttribute) > 0)
yield return property;
}
}
otherwise, you can subclass Label to a NonTranslatableLabel, apply the attribute to the class and use it instead of Label in your "father" control.
[NonTranslatable]
public class NonTranslatableLabel : Label
===================
for each of your controls you can do:
myCustomControl.GetType()
.GetCustomAttributes(true)
.Where(item => item is DoNotTranslateAttribute);
for instance you could enumerate all your "non-translatable" controls like this:
public IEnumerable<Control> GetNonTranslatableChildren(Control control)
{
foreach(Control c in control.Controls)
{
if(
c.GetType()
.GetCustomAttributes(true)
.Count(item => item is DoNotTranslateAttribute) > 0)
yield return c;
}
}
You can use GetCustomAttributes method to find out if the attribute has been applied or not. For example,
static readonly Type _DoNotTranslateAttribute = typeof(DoNotTranslate);
.... // other code
var t = control.GetType();
if (t.GetCustomAttributes(_DoNotTranslateAttribute, false).length > 0)
{
// do not translate
}
(disclaimer: untested/uncompiled code- just to give an idea how to use the function)
Currently I am trying to extract a collection of dynamically created controls (checkboxes and dropdownlists) from a recursive control collection (repeater). This is the code I am using.
private void GetControlList<T>(ControlCollection controlCollection, ref List<T> resultCollection)
{
foreach (Control control in controlCollection)
{
if (control.GetType() == typeof(T))
resultCollection.Add((T)control);
if (control.HasControls())
GetControlList(controlCollection, ref resultCollection);
}
}
I am having problems with the following line:
resultCollection.Add((T)control);
I get the error ...
Cannot convert type 'System.Web.UI.Control' to 'T'
Any ideas?
Problem:
Since T can be a reference type or a value type, compiler needs more information.
You can not convert and Integer to Control.
Solution:
To fix this, add where T : Control or where T : class (a more general) constraint to state that T will always be a reference type.
Example:
private void GetControlList<T>(ControlCollection controlCollection, ref List<T> resultCollection)
where T : Control
{
foreach (Control control in controlCollection)
{
//if (control.GetType() == typeof(T))
if (control is T) // This is cleaner
resultCollection.Add((T)control);
if (control.HasControls())
GetControlList(control.Controls, ref resultCollection);
}
}
You also don't need ref keyword. Since, List is a reference type, it's reference will be passed.
Change it to
var c = control as T;
if (c != null)
resultCollection.Add(c);
This will be faster than your cod, since it doesn't call GetType().
Note that it will also add controls that inherit T.
You'll also need to constrain the type parameter by adding where T : Control.
I have a dll that contains a number of classes that all inherit from a CommandBase class. I'm trying to get instances of all of these classes (CommandA, CommandB, CommandC, etc...) using reflection in C# so that I can call a specific method on each one. Here is what I have so far:
//get assemblies in directory.
string folder = Path.Combine(HttpContext.Current.Server.MapPath("~/"), "bin");
var files = Directory.GetFiles(folder, "*.dll");
//load each assembly.
foreach (string file in files)
{
var assembly = Assembly.LoadFile(file);
if (assembly.FullName == "MyCommandProject")
{
foreach (var type in assembly.GetTypes())
{
if (!type.IsClass || type.IsNotPublic) continue;
if(type is CommandBase)
{
var command = Activator.CreateInstance(type) as CommandBase;
}
}
}
}
I'm having 2 issues. The 1st issue is that the line "if(type is CommandBase") gives the following warning:
The given expression is never of the provided type CommandBase.
The 2nd issue is that I can't figure out how to get an instance of the actual object (CommandA, CommandB, etc...), just converting it to CommandBase isn't enough.
This is the method I use to load up based on an interface.
private static List<T> GetInstances<T>()
{
return (from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof (T)) && t.GetConstructor(Type.EmptyTypes) != null
select (T) Activator.CreateInstance(t)).ToList();
}
And here's the same function that pulls back based on base class.
private static IList<T> GetInstances<T>()
{
return (from t in Assembly.GetExecutingAssembly().GetTypes()
where t.BaseType == (typeof(T)) && t.GetConstructor(Type.EmptyTypes) != null
select (T)Activator.CreateInstance(t)).ToList();
}
Of course it would need to be modified slightly to point at the reference you're loading.
You must change
if(type is CommandBase)
to
if(type.IsSubclassOf(typeof(CommandBase)))
If the IsSubclassOf is the converse of IsAssignableFrom. That is, if t1.IsSubclassOf(t2) is true, then t2.IsAssignableFrom(t1) is also true.
Change type is CommandBase to typeof(CommandBase).IsAssignableFrom(type)
That's because your type variable is a Type, not a CommandBase.
You want
if(type == typeof(CommandBase))
(Thanks Greg for the correction)
Under a given namespace, I have a set of classes which implement an interface. Let's call it ISomething. I have another class (let's call it CClass) which knows about ISomething but doesn't know about the classes which implement that interface.
I would like that CClass to look for all the implementation of ISomething, instantiate an instance of it and execute the method.
Does anybody have an idea on how to do that with C# 3.5?
A working code-sample:
var instances = from t in Assembly.GetExecutingAssembly().GetTypes()
where t.GetInterfaces().Contains(typeof(ISomething))
&& t.GetConstructor(Type.EmptyTypes) != null
select Activator.CreateInstance(t) as ISomething;
foreach (var instance in instances)
{
instance.Foo(); // where Foo is a method of ISomething
}
Edit Added a check for a parameterless constructor so that the call to CreateInstance will succeed.
You can get a list of loaded assemblies by using this:
Assembly assembly = System.Reflection.AppDomain.CurrentDomain.GetAssemblies()
From there, you can get a list of types in the assembly (assuming public types):
Type[] types = assembly.GetExportedTypes();
Then you can ask each type whether it supports that interface by finding that interface on the object:
Type interfaceType = type.GetInterface("ISomething");
Not sure if there is a more efficient way of doing this with reflection.
A example using Linq:
var types =
myAssembly.GetTypes()
.Where(m => m.IsClass && m.GetInterface("IMyInterface") != null);
foreach (Type t in Assembly.GetCallingAssembly().GetTypes())
{
if (t.GetInterface("ITheInterface") != null)
{
ITheInterface executor = Activator.CreateInstance(t) as ITheInterface;
executor.PerformSomething();
}
}
You could use something like the following and tailor it to your needs.
var _interfaceType = typeof(ISomething);
var currentAssembly = System.Reflection.Assembly.GetExecutingAssembly();
var types = GetType().GetNestedTypes();
foreach (var type in types)
{
if (_interfaceType.IsAssignableFrom(type) && type.IsPublic && !type.IsInterface)
{
ISomething something = (ISomething)currentAssembly.CreateInstance(type.FullName, false);
something.TheMethod();
}
}
This code could use some performance enhancements but it's a start.
Maybe we should go this way
foreach ( var instance in Assembly.GetExecutingAssembly().GetTypes().Where(a => a.GetConstructor(Type.EmptyTypes) != null).Select(Activator.CreateInstance).OfType<ISomething>() )
instance.Execute();