C# 如何通过字符串正确访问UserControl公共属性

C# 如何通过字符串正确访问UserControl公共属性,c#,asp.net,user-controls,C#,Asp.net,User Controls,我在页面上有一组用户控件,它们根据条件动态加载,以运行各种报告(条件驱动程序)。每个控件都公开了一个或多个属性,这些属性将用于从数据库查询中获取数据。因为每个报表的控件都不同,所以我编写了一个过程来按名称访问相应控件的属性,以便将其发送到代码隐藏(C#)中的数据库查询。我已设置好访问公共财产,如下所示: stringVal = userControl.Attributes[stringName].ToString(); 它告诉我我需要新的东西。我不明白如何通过字符串名动态访问该属性。在我的即时

我在页面上有一组用户控件,它们根据条件动态加载,以运行各种报告(条件驱动程序)。每个控件都公开了一个或多个属性,这些属性将用于从数据库查询中获取数据。因为每个报表的控件都不同,所以我编写了一个过程来按名称访问相应控件的属性,以便将其发送到代码隐藏(C#)中的数据库查询。我已设置好访问公共财产,如下所示:

stringVal = userControl.Attributes[stringName].ToString();
它告诉我我需要新的东西。我不明白如何通过字符串名动态访问该属性。在我的即时窗口中,我可以看到我想要的财产;但是,它不是一个“属性”,如
control.Attributes.Count=0
。那么,我需要如何正确设置它,以便通过字符串名访问它?我需要用什么东西装饰房子吗


提前感谢您。

您需要探索反思。它涉及到操作.NET类型(类、结构、枚举等)的元数据。但是,如果您在部分信任的共享主机中运行应用程序,则可能根本无法运行任何类型的反射代码(服务器上的安全限制)。如果是这种情况,请先测试一个小/快速的示例(在您的主机上),然后做出适当的决定:是重新设计应用程序还是更改主机

可能对您有用的与反射相关的代码段(将其粘贴到用户控件类中的某个位置,因为
this.GetType()
很重要:

var properties = this.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

foreach (var p in properties)
{
    string propertyName = p.Name;
}

还有其他获取类型的方法;例如,
typeof(yourclassname)
;您还可以从给定的程序集(dll)反射/获取所有类型,等等。

下面,我编写了一个包装类,您可以使用它按字符串名称设置/获取包装类的公共字段或属性

首先,让我们看看如何在具有公共字段或属性StartDate和SocialSecurityNumber的类上使用它

// First create the instance we'll want to play with
MyUserControl myControlInstance = new MyUsercontrol();
// MyUserContol has two properties we'll be using
// DateTime StartDate
// int SocialSecurityNumber

// Now we're creating a map to facilitate access to the properties
// of "myControlInstance" using strings
PropertyMap<MyUserControl> map = 
             new PropertyMap<MyUserControl>(myControlInstance);

// Since the map is directed toward "myControlInstance"
// this line is equivalent to:
// myControlInstance.StartDate = Datetime.Now;
map.Set<DateTime>("StartDate", DateTime.Now);

// This line is equivalent to:
// ssn = myUsercontrol.SocialSecurityNumber;
int ssn = map.Get<int>("SocialSecurityNumber");
//首先创建我们要使用的实例
MyUserControl myControlInstance=新的MyUserControl();
//MyUserControl有两个属性,我们将使用它们
//日期时间起始日期
//国际社会安全号码
//现在,我们正在创建一个地图,以方便访问属性
//使用字符串创建“myControlInstance”的
属性映射=
新属性映射(MyControl实例);
//因为映射指向“myControlInstance”
//这一行相当于:
//myControlInstance.StartDate=Datetime.Now;
Set(“StartDate”,DateTime.Now);
//这一行相当于:
//ssn=myUsercontrol.SocialSecurityNumber;
int ssn=map.Get(“SocialSecurityNumber”);
现在来看看它是如何实施的:

public class PropertyMap<T>
{
    readonly T Instance;

    public PropertyMap(T instance)
    {
        Instance = instance;
    }

    public U Get<U>(string PropertyName)
    {
        // Search through the type's properties for one with this name
        // Properties are things with get/set accessors
        PropertyInfo property = typeof(T).GetProperty(PropertyName);
        if (property == null)
        {
            // if we couldn't find a property, look for a field.
            // Fields are just member variables, but you can only
            // manipulate public ones like this.
            FieldInfo field = typeof(T).GetField(PropertyName);
            if (field == null)
                throw new Exception("Couldn't find a property/field named " + PropertyName);
            return (U)field.GetValue(Instance);
        }
        return (U)property.GetValue(Instance, null);
    }

    public void Set<U>(string PropertyName, U value)
    {
        // Search through the type's properties for one with this name
        PropertyInfo property = typeof(T).GetProperty(PropertyName);
        if (property == null)
        {
            // if we couldn't find a property, look for a field.
            FieldInfo field = typeof(T).GetField(PropertyName);
            if (field == null)
                throw new Exception("Couldn't find a property/field named " + PropertyName);
            field.SetValue(Instance, value);
            return;
        }
        property.SetValue(Instance, value, null);
    }
}
公共类属性映射
{
只读T实例;
公共属性映射(T实例)
{
实例=实例;
}
公共U获取(字符串属性名称)
{
//在类型的属性中搜索具有此名称的属性
//属性是具有get/set访问器的东西
PropertyInfo property=typeof(T).GetProperty(PropertyName);
if(属性==null)
{
//如果找不到属性,请查找字段。
//字段只是成员变量,但您只能
//像这样操纵公众。
FieldInfo field=typeof(T).GetField(PropertyName);
如果(字段==null)
抛出新异常(“找不到名为“+PropertyName”的属性/字段);
返回(U)字段。GetValue(实例);
}
return(U)property.GetValue(实例,null);
}
公共无效集(字符串PropertyName,U值)
{
//在类型的属性中搜索具有此名称的属性
PropertyInfo property=typeof(T).GetProperty(PropertyName);
if(属性==null)
{
//如果找不到属性,请查找字段。
FieldInfo field=typeof(T).GetField(PropertyName);
如果(字段==null)
抛出新异常(“找不到名为“+PropertyName”的属性/字段);
field.SetValue(实例,值);
返回;
}
SetValue(实例,值,null);
}
}

new up意味着您将创建该用户控件的一个新实例。例如,UserControl usrCtrl=new UserControl使用反射并不是一个很好的方法。例如,如果您知道要向这些不同的控件类型询问它们的
名称,只需创建一个具有指定该属性然后从中派生控件。对不起,我需要引用哪个using语句“Instance”。您是否在问,当您只有一个映射时,如何访问内部实例?在我提供的实现中,实例成员是私有的,但您可以放置一个“public”在它前面,然后作为map.Instance访问它。例如,不,实际上,我将代码粘贴到我的项目中,并在添加using System之后。PropertyInfo和FieldInfo的反射引用了除Instance之外的所有内容。查看您的代码,该实例似乎需要using语句。我在System.Ref中找到InstanceBindingFlags,但我不确定Instance指的是什么。多么奇怪-“Instance”是PropertyMap类的成员,但不是类本身。我能够编译并运行代码。也许如果您用mWrapped替换大写的实例文本,看看它是否会生成相同的错误?还有,哪一行生成了错误?mWrapped也不起作用,并且我的机器在调试了几次之后确实变慢了es;所以,我重新启动了它并再次尝试,它神奇地工作了。谢谢你的帮助。这个答案也非常有用,我可能会用它来代替以前的答案。谢谢你Hari。