C# Func<>委托属性设置器问题

3
我正在尝试使用委托返回一个类型为IDocumentTemplateProvider的对象,代码如下:
public static class DocumentTemplateProvider
{
    private static Func<IDocumentTemplateProvider> _docTemplateProvider;

    public static void SetdocTemplateProvider(Func<IDocumentTemplateProvider> docTemplateProvider)
    {
        _docTemplateProvider = docTemplateProvider;
    }

    public static void SetDocTemplateProvider<T>() where T : IDocumentTemplateProvider, new()
    {
        _docTemplateProvider = () => new T();
    }

    public static IDocumentTemplateProvider TemplateProvider
    {
        get { return _docTemplateProvider(); }
    }
}

然而,当我使用以下方式进行调用时:
private static readonly IDocumentTemplateProvider _template = DocumentTemplateProvider.TemplateProvider;

_template 总是为 null。我对 C# 中的 Func<> 委托还比较新,所以我无法看出自己做错了什么。有人能指点我正确的方向吗?

谢谢

更新:为了消除任何困惑,我已经添加了完整的代码,其中 _template 被初始化并按原样使用:

 public class DocumentModule : IHttpModule
{
        private static readonly IDocumentTemplateProvider _template = DocumentTemplateProvider.TemplateProvider;

        public void Init(HttpApplication context)
        {
            context.BeginRequest += OnBeginRequest;
            context.EndRequest += OnEndRequest;
        }      

        public void Init(HttpApplication context)
        {
            context.BeginRequest += OnBeginRequest;
            context.EndRequest += OnEndRequest;
        }

        private void OnBeginRequest(object sender, EventArgs eventArgs)
        {
            _template.SetProvider();
        }

        private void OnEndRequest(object sender, EventArgs e)
        {
            _template.Finalize();
        }        

        public void Dispose()
        {
        }
}

你将“_template”设置为“DocumentTemplateProvider.TemplateProvider”,这是一个返回“_docTemplateProvider”的属性,据我们所知,“_docTemplateProvider”从未被设置过? - Blorgbeard
@AlexeiLevenkov,这就是我拥有的全部内容 - DocumentTemplateProvider类中没有省略的代码! - ke3pup
嗯...我有点困惑...如果那是方法的一部分,你应该会得到NRE,但你现在展示的方式(static readonly字段)应该会在类型实例化期间引发异常,而该类型应该已经死亡了...绝对是一个有趣的问题,但也绝对不是实际的问题(我假设你真的没有计划编写依赖于静态初始化随机顺序的代码)。 - Alexei Levenkov
@AlexeiLevenkov 我已经更新了问题并附上了完整的代码。 - ke3pup
感谢您更新帖子。不幸的是,我不知道为什么它会表现出这种方式。我不认为这段代码能够工作或者像您观察到的那样产生“null”。需要有很多静态字段初始化经验的人才能解决您的难题。请注意,使用静态字段通常会受到反对,大多数人没有足够的经验来处理这种情况。 - Alexei Levenkov
显示剩余3条评论
1个回答

1

它是 null,因为它从未被设置过。你有两个 Void 方法来设置 _docTemplateProvider 变量,所以你需要先调用它们,就像下面的示例代码一样。

class Program
{
    private static void Main()
    {
        DocumentTemplateProvider.SetDocTemplateProvider<Test>();
        //OR
        DocumentTemplateProvider.SetdocTemplateProvider(() => new Test());

        IDocumentTemplateProvider _template = DocumentTemplateProvider.TemplateProvider;

        Console.ReadLine();
    }

    public static class DocumentTemplateProvider
    {
        private static Func<IDocumentTemplateProvider> _docTemplateProvider;

        public static void SetdocTemplateProvider(Func<IDocumentTemplateProvider> docTemplateProvider)
        {
            _docTemplateProvider = docTemplateProvider;
        }

        public static void SetDocTemplateProvider<T>() where T : IDocumentTemplateProvider, new()
        {
            _docTemplateProvider = () => new T();
        }

        public static IDocumentTemplateProvider TemplateProvider
        {
            get { return _docTemplateProvider(); }
        }
    }
}

internal interface IDocumentTemplateProvider
{
}

public class Test : IDocumentTemplateProvider
{
}

请注意,OP代码中的_templatepublic static readonly IDocumentTemplateProvider _template,这涉及到静态字段的初始化,与在Main方法中调用静态方法完全不同...目前尚不清楚OP实际上是否在询问这个问题。 - Alexei Levenkov
无论如何,“_template”都没有被设置,不是吗? - Ricky Gummadi
由于在 OP 的代码中它是一个静态只读字段,因此应该在第一次使用之前由运行时初始化 - 在这种情况下,初始化程序是 DocumentTemplateProvider.TemplateProvider(再次是引用静态字段的静态属性)。我预计会出现 NRE(因为 _docTemplateProvider 在那时应该仍然为 null),但不知何故 OP 得到了常规的 null - Alexei Levenkov
我期望它是一个null,直到他在构造函数中调用SetdocTemplateProvider(); 或在执行return _docTemplateProvider()之前检查它是否为null; - Ricky Gummadi
_docTemplateProvider 确实是 null,但 TemplateProvider 调用 委托 - 因此在我看来 _docTemplateProvider() 应该抛出异常,因为代码中没有任何 null 检查... - Alexei Levenkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接