PropertyInfo.SetValue not not“sticking” [英] PropertyInfo.SetValue not "sticking"

查看:98
本文介绍了PropertyInfo.SetValue not not“sticking”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这可能是一个很长的问题,但这里是:



首先,为什么我不能使用内置的本地化:

内置本地化仅在#1,控件属性应用了Localizable属性时才有效,而#2仅在它们是顶级属性时才有效。因为我需要能够在没有应用Localizable属性的项目上本地化嵌套属性,所以我必须自己滚动。



所以,所有表格在这个项目中衍生出一个基本形式,它有以下两个功能:



Ok, this may be a long question, but here it is:

First, why I can't use built in localization:
The built-in localization only works if #1, the control properties have the "Localizable" attribute applied to them, and #2 only if they are top level properties. Since I need to be able to localize nested properties on items that don't have the Localizable attribute applied, I have to roll my own.

So, all the forms in this project derive from a single base form, which has the following two functions on it:

private void ResetResources()
{
    for (int i = 0; i < Controls.Count; i++)
    {
        Control c = Controls[i];
        ApplyResource(ref c, "Screens." + this.Name);
    }

    Invalidate(true);
}

private void ApplyResource(ref Control c, string baseName)
{
    ResourceService.ApplyResource(ref c, baseName + "." + c.Name);

    if (c.HasChildren)
    {
        for (int i = 0; i < c.Controls.Count; i++)
        {
            Control sc = c.Controls[i];
            ApplyResource(ref sc, baseName + "." + c.Name);
        }
    }
}





更改文化时调用ResetResources 。我有一个静态资源服务,表单通过调用此函数使用:





ResetResources is called when the culture is changed. I have a single static resource "service" that the form uses by calling this function:

internal static void ApplyResource(ref Control c, string fullControlName)
{
    string resourceName = fullControlName + ".Text";
    string value = c.Text;

    try
    {
        ResourceSet rSet = _resourceManager.GetResourceSet(_currentCulture, true, true);

        Dictionary<string, string> resources = GetResourcesFor(rSet, fullControlName);

        foreach (KeyValuePair<string, string> kvp in resources)
            SetProperty(ref c, kvp.Key, kvp.Value);
    }
    catch { }

    if (!string.IsNullOrEmpty(value))
        c.Text = value;
}





大部分是非常基本的,它使用ResourceManager和ResourceSet来获取适当的资源。 GetResourcesFor(我不会发布代码,因为它不相关)只是从控件名称开始获取所有资源,并且效果很好。



问题当我通过反射设置属性时进来。由于我不知道属性名称是什么(它在资源文件中),我使用SetProperty和GetSubObject函数,它是:





Most of it is pretty basic, it uses a ResourceManager and ResourceSet to get the appropriate resources. The GetResourcesFor (which I won't post the code for since its irrelevant) just gets all the resources beginning with the control name, and that works great.

The problem comes in when I set the properties through reflection. Since I don't know what the property name is (its in the resource file), I use the SetProperty and GetSubObject function, which is:

private static void SetProperty(ref Control c, string property, object value)
{
    string[] propPath = null;

    if (property.Contains('.'))
        propPath = new string[] { property };
    else
        propPath = property.Split('.');

    object currentObject = c;
    object parentObject = c;
    PropertyInfo pInfo = null;

    for (int i = 0; i < propPath.Length; i++)
    {
        parentObject = currentObject;
        currentObject = GetSubObject(currentObject, propPath[i], out pInfo);

        if (currentObject == null)
            return;
    }

    if (pInfo != null)
    {
        if (c.InvokeRequired)
            c.Invoke((MethodInvoker)delegate { pInfo.SetValue(parentObject, value, null); });
        else
        {
            pInfo.SetValue(parentObject, value, null);
            c.Invalidate(true);
        }
    }
}

private static object GetSubObject(object obj, string propName, out PropertyInfo pInfo)
{
    //Figure out if it's an index property...
    bool isIndex = false;
    int index = 0;
    pInfo = null;
    string pName = propName;

    if (propName.Contains('['))
    {
        isIndex = true;
        string idxStr = propName.Substring(propName.IndexOf('[') + 1);
        idxStr = idxStr.TrimEnd(']');

        if (!int.TryParse(idxStr, out index))
            return null;

        pName = propName.Substring(0, propName.IndexOf('['));
    }

    pInfo = obj.GetType().GetProperty(pName);

    if (pInfo == null)
        return null;

    if (!isIndex)
        return pInfo.GetValue(obj, null);
    else
    {
        IList objList = pInfo.GetValue(obj, null) as IList;

        if (objList == null)
            return null;

        return objList[index];
    }
}





GetSubObject和一切正常,如果我调试并在pInfo.SetValue之后设置一个断点,该属性设置正确,但是当堆栈展开回形式时,该属性永远不会更新!这似乎不是一个绘图问题,我真的不知所措,因为我在同一时间设置其他地方的属性值,并且由于某种原因这不起作用!



我的想法是因为我正在通过Controls集合编制索引,由于某种原因它不会保存我的更改(因此在函数原型中所有无意义的ref)。我只是不知道修复是什么。这应该是动态的,所以我不能硬编码所有控件名称或属性,它只是应该工作。



任何帮助都会很棒。



The GetSubObject and everything works, and if I debug and set a breakpoint just after the pInfo.SetValue, the property is set correctly, but when the stack unwinds back to the form, the property is never updated! This doesn't seem to be a drawing problem, I'm really at a loss as I'm setting the property values in other places in the same fashion and for some reason this isn't working!

My idea is that because I'm indexing through the Controls collection that for some reason it isn't saving my changes (hence all the pointless "ref" in the function prototypes). I just don't know what the fix is. This is supposed to be dynamic, so I can't hard-code all the control names nor the properties, its just supposed to "work".

Any help would be great.

推荐答案

好的......我发现了......



问题是这个line:



Ok... I found it...

The problem was this line:

internal static void ApplyResource(ref Control c, string fullControlName)
        {
            string resourceName = fullControlName + ".Text";
            string value = c.Text;
 
            try
            {
                ResourceSet rSet = _resourceManager.GetResourceSet(_currentCulture, true, true);
 
                Dictionary<string,> resources = GetResourcesFor(rSet, fullControlName);
 
                foreach (KeyValuePair<string,> kvp in resources)
                    SetProperty(ref c, kvp.Key, kvp.Value);
            }
            catch { }
            
            //THE PROBLEM WAS THESE TWO LINES
            if (!string.IsNullOrEmpty(value))
                c.Text = value;
        }





最初我写这个只是设置.Text属性而SetProperty返回一个字符串,我错过了删除这两行。



无论如何都要感谢:)



Originally I wrote this to just set a .Text property and SetProperty was returning a string, I missed removing those two lines.

Thanks for looking anyway :)


这篇关于PropertyInfo.SetValue not not“sticking”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆