2017-05-09 185 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' ..這不起作用。這個名字也不一樣 –