2017-05-09 118 views
0

所以我得到了下面的类...匹配类型

public partial class CommandBar : UserControl { .. } 

...我包括像这样的.ascx文件...

<%@ Register Src="~/.../CommandBar.ascx" TagName="CommandBar" TagPrefix="uc1" %> 

... 

<uc1:CommandBar ID="CommandBarTop" runat="server" ... /> 

我目前的目标是创建一个通用方法,允许用户将所有控件设置为只读递归。该方法应该提供一个可选参数来指定要忽略的控件的List<Type>。在这个列表中,我想通过与typeof(CommandBar)这个CommandBar忽略这些。

一切正常工作,但我有点麻烦找出正确的方式来匹配这些类型。

请考虑以下内容;

Object o; // control to check, in this case the `CommandBarTop` object 
Type t; // type to ignore 

我希望它是那么容易这样的:

if (o is t){ 
    // ignore 
} 

...但我得到一个语法异常“的常数值,预计”。所以我试着用下面的设置:

if (t == typeof(o)){ 
    // ignore 
} 

它确实编译,但没有像预期的那样工作。这个问题似乎是一种类型错配。在调试纵观我得到如下:

t => {Name = "CommandBar" FullName = "My.Name.Space.Controls.CommandBar"} System.Type {System.RuntimeType} 
o => {ASP.controls_commandbar_ascx} object {ASP.controls_commandbar_ascx} 

o.base实际上是t类型,但首先它是不可访问的第二个方法应该是通用的,检查的基本类型匹配可能不会总是做我想做的事。

我假设ASP.NET在运行时生成一个控件包装,然后发送给用户。这个假设是基于我在调试器中看到的汇编代码库。它说以下内容:

t.Assembly.CodeBase => "file:///.../bin/My.Name.Space.Project.DLL" string 
o.GetType().Assembly.CodeBase => "file:///C:/Windows/Microsoft.NET/Framework/.../Temporary ASP.NET Files/root/.../App_Web_....DLL" string 

我也试过匹配类型GUID,但由于他们基本上不是同一类型,不能正常工作。


编辑1

我想这可能帮助,如果我告诉你我的方法来设置控件为只读递归

public static void SetControlRecursivelyReadOnly(Object control, Boolean readOnly, IEnumerable<Type> controlTypesToIgnore = null) 
{ 
    if (null == control) 
    { 
     return; 
    } 

    new List<KeyValuePair<Type, String>> 
    { 
     // define all types which are relevant to access possible child controls 
     new KeyValuePair<Type, String>(typeof(ControlCollection), "Controls"), 
     new KeyValuePair<Type, String>(typeof(TableRow), "Rows"), 
     new KeyValuePair<Type, String>(typeof(TableCell), "Cells") 
    }.ForEach(x => 
       { 
        // get defined property 
        Object property = typeof(Reflection).GetMethod("GetProperty") 
                 .MakeGenericMethod(x.Key) 
                 .Invoke(null, 
                   new[] 
                   { 
                    control, 
                    x.Value 
                   }); 

        // check if property is found and is IENumerable 
        if (!(property is IEnumerable)) 
        { 
         return; // continues the foreach loop 
        } 

        // call recursive 
        foreach (Object o in (IEnumerable) property) 
        { 
         // <--- TODO CHECK IF CONTROL TYPE SHOULD BE IGNORED ---> 
         SetControlRecursivelyReadOnly(o, readOnly); 
        } 
       }); 

    // set relevant properties accordingly to readOnly parameter 
    new List<Tuple<PropertyInfo, Boolean>> 
      { 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("ReadOnly"), readOnly), 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("EnableButtons"), !readOnly), 
       new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("Enabled"), !readOnly) 
      }.Where(x => null != x.Item1) 
      .ToList() 
      .ForEach(x => x.Item1.SetValue(control, x.Item2, null)); 
} 

来我现在的问题;任何人有一个想法如何解决这个问题?

在此先感谢!

+0

你的意思是,当你谈论组件?也许“控件”(TextBox,Label ...)?你可以添加一些例子吗? – Emanuele

+0

@Emanuele是的,先生,我的意思是控制。我相应地更新了我的问题。你用TextBox,Label aso给出的例子。正是我的意思。 Ofc也有Panels,Tables,DropDownLists,..有时候会有一个属性叫做“Controls”,“Rows”或者“Cells”本身,这就是为什么我实现它递归去获得页面内的所有控件 –

回答

0

您需要递归循环页面中的所有控件。

public void FindChildControlsRecursive(Control control) 
    { 
     foreach (Control childControl in control.Controls) 
     { 
      // add .BaseType in the next line if it's a UserControl 
      if (childControl.GetType() == typeof(T)) 
      { 
       _foundControls.Add((T)childControl); 
      } 
      else 
      { 
       FindChildControlsRecursive(childControl); 
      } 
     } 
    } 

    private readonly List<T> _foundControls = new List<T>(); 
    public IEnumerable<T> FoundControls 
    { 
     get { return _foundControls; } 
    } 

以同样的方式,您可以设置一个包含要排除的控件的属性。

您可以检查:How to get the "typeof" of a custom user control

+0

我已经有了递归函数,那不是问题。问题是类型的匹配。你的'control.GetType()== typeof(T)'方法不起作用。因为T已经是一个Type,调用typeof(T)将返回一个RuntimeType,这不是我所需要的。也因为控制不是相同的类型,它不会工作。再次阅读我的问题 –

+0

对不起,我会编辑我的文章。尝试使用BaseType。我会检查我的VS解决方案。 – Emanuele

+0

是的,BaseType确实指的是正确的类型,与此匹配应该可行。问题是如果我将它实现为始终检查BaseType我很确定这在当时最不起作用,因为几乎每个Control的BaseType都是'WebControl' ..如果我告诉方法忽略WebControl,那么什么都不会发生。我已经想到了这种方法,但似乎我遇到了问题很快 –

0

尝试用你的类型的名称道具。像下面的东西应该工作

if (typeof(o).Name == t.GetType().Name) { // ignore }

+0

在t上调用'.GetType()'(它已经是'Type'类型)将返回一个'System.RuntimeType' ..这不起作用。这个名字也不一样 –