是否可以在基类上创建静态字段,但影响在子类上创建?

时间:2009-07-14 15:46:01

标签: c# oop

我需要像下面的代码一样创建基类。

public class ResourceBase
{
    protected static IDictionary<string, XDocument> resources;

    protected static IDictionary<string, XDocument> Resources
    {
        get
        {
            if (resources == null)
            {
                // cache XDocument instance in resources variable seperate by culture name.
                // load resx file to XDocument
            }

            return resources;                
        }
    }

    protected static string GetString(string resourceKey)
    {
        return GetString(resourceKey, System.Threading.Thread.CurrentThread.CurrentUICulture.Name);
    }

    protected static string GetString(string resourceKey, string cultureName)
    {
        // get data from XDocument instance
        var result = (
                        from rs in Resources
                        let node = rs.Value.Root.Elements(XName.Get("data")).SingleOrDefault<XElement>(x => x.Attribute(XName.Get("name")).Value == resourceKey)
                        where
                                (rs.Key == DEFAULT_CULTUREKEY || cultureName == rs.Key) &&
                                node != null
                        orderby cultureName == rs.Key descending
                        select node.Element(XName.Get("value"))
                     ).FirstOrDefault<XElement>();

        return result.Value;
    }
}

接下来,我创建子类,如下面的代码。

public class MainResource : ResourceBase
{
    public static string AppName
    {
        return GetString("AppName");
    }
}

public class OtherResource : ResourceBase
{
    public static string OtherName
    {
        return GetString("OtherName");
    }
}

我有一些问题,因为基类中的资源变量。所有子类都使用一些Resource变量。因此,它们总是使用相同的缓存XDocument实例。你有什么想法来修复我的源代码吗?

PS。我发现了一些像ContextStaticAttribute这样的属性,它表明静态字段的值对于特定的上下文是唯一的。我认为一个特定的上下文应该是差异线程。所以,我不能用它来解决这个问题。

谢谢,

5 个答案:

答案 0 :(得分:3)

使基类成为抽象,不提供Resources的实现。然后派生类可以将它自己的资源提供给基类​​GetString方法。

答案 1 :(得分:3)

这似乎要求Singleton实现。你的基类的原因是共享逻辑,对吗?不要将所有内容都设置为静态,而是实现Singleton模式,以便每个子类都有自己的实例,所有实例都共享基类中的逻辑。

这将允许他们在共享行为逻辑时进行独立缓存。

答案 2 :(得分:0)

似乎您需要每次为您的子课程缓存。缓存XDocument时,需要提供与子类不同的键。您可以将其添加到Base类

abstract string ResourceName { get; };
protected static IDictionary<string, XDocument> Resources
{
    get
    {
        if (resources == null)
        {
            //Cache the XDocument with a key based on ResourceName.
        }

        return resources;                
    }
}

然后你的MainResource有

string ResourceName { get { return "AppName"; } }

public static string AppName
{
    return GetString(ResourceName);
}

答案 3 :(得分:0)

1.通过使用静态资源变量缓存所有资源来解决此问题的解决方案取决于子类的类型。

public class ResourceBase
{
    protected static IDictionary<Type, IDictionary<string, XDocument>> resources;
    protected static IDictionary<string, XDocument> Resources
    {
        get
        {
            if (resources == null)
            {
                // cache XDocument instance in resources variable seperate by type and culture name.
                // load resx file to XDocument
            }

            return resources;
        }
    }
}

顺便说一句,当我获得资源值时,此解决方案每次都需要使用以下代码来输入Child类。此外,我测试了这个解决方案大约10k - 100k轮,它可以检索 6,000次操作/秒的数据。因此,我不能将此解决方案用于实际应用程序,因为每个Web请求必须检索超过50个操作。

public static Type GetCallerType(Type baseClass, int skipFrames)
{
    StackTrace trace = new StackTrace(skipFrames + 1, false);
    Type callerType = null;

    for (int i = 0; i < trace.FrameCount; ++i)
    {
        StackFrame frame = trace.GetFrame(i);
        Type type = frame.GetMethod().DeclaringType;

        if (type == baseClass || IsInheritFrom(type, baseClass))
        {
            callerType = type;
        }
        else
        {
            break;
        }
     }

     if (callerType != baseClass)
        return callerType;
     else
        return null;
}

答案 4 :(得分:0)

2.仅使用方法扩展解决此问题的更简单的解决方案。

强类型资源文件

[ResourceInfo("~/Views/Home", "Index")]
public class IndexView
{
    protected static IDictionary<string, XDocument> resources = new Dictionary<string, XDocument>();

    public static string Title
    {
        get
        {
            return resources.GetString("Title");
        }
    }
}

资源助手文件

public static class ResourceHelper
{
    const string RESOURCE_EXTENSION = "resx";
    const string DEFAULT_CULTUREKEY = "(default)";

    public static string GetString(this IDictionary<string, XDocument> resource, string resourceKey)
    {
        return resource.GetString(resourceKey, System.Threading.Thread.CurrentThread.CurrentUICulture.Name);
    }

    public static string GetString(this IDictionary<string, XDocument> resource, string resourceKey, string cultureName)
    {
        if (resource.Count == 0)
            resource.LoadResource();

        // retrieve data
    }

    public static void LoadResource(this IDictionary<string, XDocument> resource)
    {
        // logic to load resource
    }

我使用#solution1这样的测试用例测试了这个逻辑。但我发现了非常有趣的结果。它可以检索超过120,000次操作/秒。所以,这是我的最终答案,因为它简单,干净,快速。

<强>谢谢,