为什么PreApplicationStartMethodAttribute()在SharePoint 2013中不起作用?

Ell*_*ood 6 sharepoint routing global-asax sharepoint-2013

在.NET 4(.5)中有这样的惊人Attribute:PreApplicationStartMethodAttribute我想在SharePoint 2013中使用它,所以我不必直接app_startglobal.asax文件中编辑方法.

由于SP2013运行的是正确版本的.NET,我认为这个属性可以正常工作......但似乎并非如此.

有没有人想出如何使用它?或解释为什么它不能工作?

小更新:在我看到的system.web dll中,PreApplicationStartMethodAttribute由下面的类调用.

// System.Web.Compilation.BuildManager
internal static ICollection<MethodInfo> GetPreStartInitMethodsFromAssemblyCollection(IEnumerable<Assembly> assemblies, bool buildingFromCache)
{
    List<MethodInfo> list = new List<MethodInfo>();
    foreach (Assembly current in assemblies)
    {
        PreApplicationStartMethodAttribute[] array = null;
        try
        {
            array = (PreApplicationStartMethodAttribute[])current.GetCustomAttributes(typeof(PreApplicationStartMethodAttribute), true);
        }
        catch
        {
        }
        if (array == null || !array.Any<PreApplicationStartMethodAttribute>())
        {
            if (buildingFromCache)
            {
                return null;
            }
        }
        else
        {
            PreApplicationStartMethodAttribute[] array2 = array;
            for (int i = 0; i < array2.Length; i++)
            {
                PreApplicationStartMethodAttribute preApplicationStartMethodAttribute = array2[i];
                MethodInfo methodInfo = null;
                if (preApplicationStartMethodAttribute.Type != null && !string.IsNullOrEmpty(preApplicationStartMethodAttribute.MethodName) && preApplicationStartMethodAttribute.Type.Assembly == current)
                {
                    methodInfo = BuildManager.FindPreStartInitMethod(preApplicationStartMethodAttribute.Type, preApplicationStartMethodAttribute.MethodName);
                }
                if (!(methodInfo != null))
                {
                    throw new HttpException(SR.GetString("Invalid_PreApplicationStartMethodAttribute_value", new object[]
                    {
                        current.FullName,
                        (preApplicationStartMethodAttribute.Type != null) ? preApplicationStartMethodAttribute.Type.FullName : string.Empty,
                        preApplicationStartMethodAttribute.MethodName
                    }));
                }
                list.Add(methodInfo);
            }
        }
    }
    return list;
}
Run Code Online (Sandbox Code Playgroud)

如果SharePoint 2013在asp.net 4.0上运行,我可能会在应用程序上调用以下内容.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe
Run Code Online (Sandbox Code Playgroud)

Joe*_*pka 2

以下只是推测,但基于实验。

我认为 SharePoint 2013 使用某种运行时程序集加载来加载任何和所有自定义代码程序集。毕竟,当我们添加 WebPart 时,应用程序不会重新编译。这里描述了如何完成此操作的简单方法:http://msdn.microsoft.com/en-us/library/d133hta4.aspx

我创建了一个简单的 ASP MVC 应用程序,在其中尝试了这种精确的技术,并在我的 global.asax 中加载了一个程序集:

 protected void Application_Start()
    {
        ObjectHandle handle = Activator.CreateInstance("ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=27b9c31f70a4bee3", "ClassLibrary1.Class1");
        Object p = handle.Unwrap();
        Type t = p.GetType();

        MethodInfo method = t.GetMethod("ToString");
        Object retVal = method.Invoke(p, null);
    }
Run Code Online (Sandbox Code Playgroud)

正在加载的程序集是我创建并放置在 GAC 中的。这个 ClassLibrary1 确实是准系统,有一个类 Class1,其中包含一个方法 ToString()。ToString 方法抛出一个异常,很容易看出它是否被调用:

public class Class1
{
    public override string ToString()
    {
        throw new ApplicationException("Joe was in the tostring");
        return base.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

该程序集还使用 AssemblyInfo.cs 文件中的 PreApplicationStartMethod:

[assembly: PreApplicationStartMethod(typeof(ClassLibrary1.JoeAssemblyStart), "Start")]
Run Code Online (Sandbox Code Playgroud)

最后有一个由 PreApplicationStartMethod 属性调用的简单类:

 public class JoeAssemblyStart
{
    public static void Start()
    {
        throw new ApplicationException("joe was here in this assembly start");
    }
}
Run Code Online (Sandbox Code Playgroud)

有趣的事情发生在运行时。当我运行此代码时,引发的异常来自 Class1 中的 ToString,而不是 JoeAssemblyStart 类。这意味着当我们在运行时加载程序集时,PreApplicationStartMethod 属性将被忽略,考虑到 ASP.NET 管道时,这并不奇怪。

当我将 ClassLibrary1 显式添加到我的 MVC 项目中并且没有动态加载它时,我还运行了该实验的一个版本。在本例中,PreApplicationStartMethod 代码按预期被调用。

总结一下:

  1. 当您向 SharePoint 2013 添加代码时,不会重建 SharePoint 2013
  2. 因此,您的代码必须以某种动态方式加载
  3. 动态加载的程序集不能早于 PreApplicationStartMethod 影响 ASP.NET 管道