匹配类型
所以我得到了下面的类...匹配类型
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));
}
来我现在的问题;任何人有一个想法如何解决这个问题?
在此先感谢!
您需要递归循环页面中的所有控件。
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; }
}
以同样的方式,您可以设置一个包含要排除的控件的属性。
我已经有了递归函数,那不是问题。问题是类型的匹配。你的'control.GetType()== typeof(T)'方法不起作用。因为T已经是一个Type,调用typeof(T)将返回一个RuntimeType,这不是我所需要的。也因为控制不是相同的类型,它不会工作。再次阅读我的问题 –
对不起,我会编辑我的文章。尝试使用BaseType。我会检查我的VS解决方案。 – Emanuele
是的,BaseType确实指的是正确的类型,与此匹配应该可行。问题是如果我将它实现为始终检查BaseType我很确定这在当时最不起作用,因为几乎每个Control的BaseType都是'WebControl' ..如果我告诉方法忽略WebControl,那么什么都不会发生。我已经想到了这种方法,但似乎我遇到了问题很快 –
尝试用你的类型的名称道具。像下面的东西应该工作
if (typeof(o).Name == t.GetType().Name) { // ignore }
在t上调用'.GetType()'(它已经是'Type'类型)将返回一个'System.RuntimeType' ..这不起作用。这个名字也不一样 –
你的意思是,当你谈论组件?也许“控件”(TextBox,Label ...)?你可以添加一些例子吗? – Emanuele
@Emanuele是的,先生,我的意思是控制。我相应地更新了我的问题。你用TextBox,Label aso给出的例子。正是我的意思。 Ofc也有Panels,Tables,DropDownLists,..有时候会有一个属性叫做“Controls”,“Rows”或者“Cells”本身,这就是为什么我实现它递归去获得页面内的所有控件 –