简体   繁体   English

必须在非泛型静态类中定义扩展方法 - 从文档中提取XML

[英]Extension method must be defined in a non-generic static class - Pulling XML from document

I'm currently writing up an upload system that takes XML from the document and will display it on a web page. 我目前正在编写一个上传系统,它从文档中获取XML并将其显示在网页上。

The issue I'm facing, is that whenever I'm adding the XML extraction part of the website, the compiler will return the error as mentioned in the title. 我面临的问题是,每当我添加网站的XML提取部分时,编译器将返回标题中提到的错误。

My code currently looks like this. 我的代码目前看起来像这样。

The part that is causing the problem is the publicstatic Xnamespace w and all the following relevant XML code. 导致问题的部分是publicstatic Xnamespace w以及以下所有相关的XML代码。 Cheers. 干杯。

<script runat="server">
    //This template is being built to allow the viewstates to be displayed and allow them to be hidden
    //or shown at the same time. The buttons are being added so we can test whether they will
    //be hidden on page use


    public string _TempFileLocation = ""; //Used to locate Word Document File Path 


    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {


            string viewStateDisplay1 = "ViewState1 is now being displayed";
            string viewStateDisplay2 = "ViewState2 is now being displayed";
           // var ViewShow = viewStateDisplay1;
           // var ViewShow2 = viewStateDisplay2; 

            if (ViewState["PageState"] == null)
            {
                ViewState["PageState"] = viewStateDisplay1;
            }

                else
                {
                    ViewState["PageState"] = viewStateDisplay2;
                    //viewStateDisplay = false;
                }
        }

    }

    //button that shows the label string
    protected void btnClick_Click(object sender, EventArgs e)
    {
        lblString.Text = ViewState["PageState"].ToString();
        lblString.Visible = true;
    }

    //button that hides the div, changing "lblstring" or adding more should be able to hide 
    //or show whatever methods / objects we want
    private void Close(object sender, EventArgs e)
    {
        lblString.Visible = !lblString.Visible;
        lblString.Visible = false;
    }


    //This will be the default set for the page. It will start on true for viewstatedisplay
    //this will be done again, but with viewstatedisplay2 for the next method regarding 
    //the two columns and displaying document and DB data. "viewStateDisplay2.Visible = true"

    //private void gotoviewStateDisplay1(object sender, EventArgs e)
    // {
    //   ViewState("PageState") = 1;
    //   viewStateDisplay1.Visible = true;
    //   viewStateDisplay2.Visible = false;
    //}

    //private void gotoviewStateDisplay2(object sender, EventArgs e)
    // {
    //   ViewState("PageState") = 2;
    //   viewStateDisplay1.Visible = false;
    //   viewStateDisplay2.Visible = true;
    //}




    //THE USER UPLOAD CONTROL. users use this to upload the document to the server
    //This has validation so they cannot upload wrong file types / too large files

   // public partial class UploadFileControl : System.Web.UI.UserControl
  //  {

        //ViewState1 

        public void XMLextractor(string _filePath)
        {

            //XML extraction code
           displayFilepath.Text = _filePath;
           _TempFileLocation = _filePath;

        }

        //names the script manager which will be used when the user attempts to upload a form / gives an error if they incorrectly attempt to upload
        protected void UploadButton_Click(object sender, EventArgs e)
        {
            //if file is located
            if (FileUploadControl.HasFile)
            {
                try
                {
                    //allow content type of document / docx
                    if (FileUploadControl.PostedFile.ContentType == "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
                    {
                        //if the file is is less than 51mb
                        if (FileUploadControl.PostedFile.ContentLength < 10485760) // 10mb)
                        {
                            //name the filename, find the path of the name
                            string filename = Path.GetFileName(FileUploadControl.FileName);
                            //path of server upload (we just need to save it as a variable to be found on the next page, as it will be made / deleted
                            FileUploadControl.SaveAs(Server.MapPath("~/") + filename);
                            //update the label with file uploaded
                            StatusLabel.Text = "Upload status: File uploaded!";

                            XMLextractor(Server.MapPath("~/") + filename);

                            //move onto template wizard page
                            //Response.Redirect("http://portal.acoura.com/admin/templatewizard.aspx", false);

                          WordprocessingDocument _TempDoc = WordprocessingDocument.Open(Server.MapPath("~/") + filename, true);

                         labelContentControls.Text = fileUpload_Displayx(GetContentControls(_TempDoc));

                            //will be used to grab the document string
                            //return;

                        }
                        else
                            //display the size the file needs to be less than
                            StatusLabel.Text = "Upload status: The file has to be less than 10mb!";
                    }
                    else
                        //tell the user only docx files are accepted
                        StatusLabel.Text = "Upload status: Only DOCX files are accepted!";
                }
                catch (Exception ex)
                {
                    //display the exception message, in which case it would be either size / type / if it's present
                    StatusLabel.Text = "Upload status: The file could not be uploaded. The following error occured: " + ex.Message;
                }


            }

        }
   // }

   //insert or link to XMLfromDocument file here. This will declare the variables
   //and take the required XML sections from the content controls of a document
   //needs to run as the file is uploaded, then return the control content titles

       // internal static class W
       //{

        //}


        public static XNamespace w =
            "http://schemas.openxmlformats.org/wordprocessingml/2006/main";

        public static XName body = w + "body";
        public static XName sdt = w + "sdt";
        public static XName sdtPr = w + "sdtPr";
        public static XName tag = w + "tag";
        public static XName val = w + "val";
        public static XName sdtContent = w + "sdtContent";
        public static XName tbl = w + "tbl";
        public static XName tr = w + "tr";
        public static XName tc = w + "tc";
        public static XName p = w + "p";
        public static XName r = w + "r";
        public static XName t = w + "t";
        public static XName rPr = w + "rPr";
        public static XName highlight = w + "highlight";
        public static XName pPr = w + "pPr";
        public static XName color = w + "color";
        public static XName sz = w + "sz";
        public static XName szCs = w + "szCs";


        public static XDocument GetXDocument(this OpenXmlPart part)
        {
            XDocument xdoc = part.Annotation<XDocument>();
            if (xdoc != null)
                return xdoc;
            using (Stream str = part.GetStream())
            using (StreamReader streamReader = new StreamReader(str))
            using (XmlReader xr = XmlReader.Create(streamReader))
                xdoc = XDocument.Load(xr);
            part.AddAnnotation(xdoc);
            return xdoc;
        }

        public static XElement GetContentControls(WordprocessingDocument document)
        {

            XElement contentControls = new XElement("ContentControls",
                document
                    .MainDocumentPart
                    .GetXDocument()
                    .Root
                    .Element(W.body)
                    .Elements(W.sdt)
                    .Select(tableContentControl =>
                        new XElement("Table",
                            new XAttribute("Name", (string)tableContentControl
                                .Element(W.sdtPr).Element(W.tag).Attribute(
                                    W.val)),
                            tableContentControl
                                    .Descendants(W.sdt)
                                    .Select(fieldContentControl =>
                                            new XElement("Field",
                                                new XAttribute("Name",
                                                    (string)fieldContentControl
                                                          .Element(W.sdtPr)
                                                          .Element(W.tag)
                                                          .Attribute(W.val)
                                                    )
                                            )
                                    )
                        )
                    )
            );
            //display the content controls in a web form in this project using this, the control will have to be added to templatewizard
            return contentControls;

            //need to mark the source which will be a file in the same directory as this for test purposes.

        }
   //display the TemplateWizard boxes and button here, hide viewstate and display viewstate2  
   //display content controls from doc on box1, field names from DB in box2
   //just create a string here that represents the final state of data being taken from XMLfromDocument


      // public string fileUpload_Displayx (XElement _contentcontrol)
      // {
      //      string str= "";
       //     str= _contentcontrol.Name.ToString();

       //    return str;

     //  }

   //public static displayDatabase(object sender, EventArgs e)
  // {

   //}
   //run the validate button on templatewizard, will mark up any problems or give green light


   //if red, allow users to replace fields in the left column, from ones in the atabase on the right


   //display upload button when validation is succesful. When Upload button runs, Take to new 
   // / existing page of reports, allow users to download this 






</script>

<!-- The following section will include all the html and forms etc !-->

<!-- on implementation, create different divs for each section, and style appropriately.  !-->
<div>


<!--Testing View state form!-->
ViewState Data: <b><asp:Label ID="lblString" runat="server"/></b>
<asp:Button ID="btnClick" runat="server" Text="Get ViewState Data" OnClick="btnClick_Click"/>
<asp:Button ID="Closeform" runat="server" Text ="Hide PageState" OnClick="Close" />


<br /><br /><br /><br /><br />

<!-- User upload control !-->
<asp:FileUpload id="FileUploadControl" runat="server" />
<asp:Button runat="server" id="UploadButton" text="Upload" onclick="UploadButton_Click" />
<asp:TextBox Text="" runat="server" ID="displayFilepath" />
<br /><br />
<asp:Label runat="server" id="StatusLabel" text="Upload status: " />

 <br /> <br /> <br /> <br />



<!-- Viewdata2, the document and data from DB will be displayed !-->

<!-- Document data !-->
<div id="box1" class="box">

    <div class="box-top">
        Data Sources inside document
    </div>
    <div class="box-middle">
        <asp:Label runat="server" id="labelContentControls" text="label of content in document" />
        <p> Test </p>
        <p> Test </p>
    </div>
    <div class="box-bottom">
    </div>
</div>    

<!--Data from DB !-->
<div id="box2" class="box">

    <div class="box-top">
        Data sources existing on the server
    </div>
    <div class="box-middle">
        <asp:Label runat="server" id="labelDatabasefields" text="label of content in database" />
        <p> Test </p>
        <p> Test </p>
    </div>
    <div class="box-bottom">
    </div>
</div>


<input type="button" value="Create Template" id="view" class="form_button"/>



</div>

Well yes, this is the problem: 是的,这是问题所在:

public static XDocument GetXDocument(this OpenXmlPart part)

That's not being declared within a top-level static non-generic class, which extension methods have to be. 这不是在顶级静态非泛型类中声明的,扩展方法必须是。

I would strongly advise you to stop mixing your code and HTML - put the code in code-behind and other classes. 我强烈建议你停止混合代码和HTML - 将代码放在代码隐藏和其他类中。 The GetXDocument method will need to be in a separate class, as it'll need to be in a static class as per the compilation error. GetXDocument方法需要在一个单独的类中,因为它需要根据编译错误在静态类中。

EDIT: One nasty alternative would be to just make it not an extension method: 编辑:一个令人讨厌的替代方案是让它不是一个扩展方法:

public static XDocument GetXDocument(OpenXmlPart part)

then your call that looks like this: 然后你的电话看起来像这样:

document.MainDocumentPart
        .GetXDocument()

will need to be: 将需要:

GetXDocument(document.MainDocumentPart)

C# allows to create extensions methods . C#允许创建扩展方法 Method with this keyword in definition, like your: 在定义中使用此关键字的方法,例如:

  public static XDocument GetXDocument(this OpenXmlPart part)

But this extension methods can be placed only in static class. 但是这种扩展方法只能放在静态类中。 You can't place them in non static class. 您不能将它们放在非静态类中。 So you need to move it to new static class and use it, or just remove this keyword and use as usual method 因此,您需要将其移动到新的静态类并使用它,或者只是删除关键字并使用通常的方法

You have defined the extension method in wrong place. 您已在错误的位置定义了扩展方法。 Define extension method GetXDocument in some static class instead of defining in Page class. 在一些静态类中定义扩展方法GetXDocument ,而不是在Page类中定义。

public static class YourStaticMethods
{
       public static XDocument GetXDocument(this OpenXmlPart part)
        {
            XDocument xdoc = part.Annotation<XDocument>();
            if (xdoc != null)
                return xdoc;
            using (Stream str = part.GetStream())
            using (StreamReader streamReader = new StreamReader(str))
            using (XmlReader xr = XmlReader.Create(streamReader))
                xdoc = XDocument.Load(xr);
            part.AddAnnotation(xdoc);
            return xdoc;
        }
}

Extension method example for adding method to string class. 将方法添加到字符串类的扩展方法示例。

namespace ExtensionMethods
{
    public static class MyExtensions
    {
        public static int WordCount(this String str)
        {
            return str.Split(new char[] { ' ', '.', '?' }, 
                             StringSplitOptions.RemoveEmptyEntries).Length;
        }
    }   
}

You can learn about Extension methods here . 您可以在此处了解扩展方法。

This method : 这个方法:

    public static XDocument GetXDocument(this OpenXmlPart part)
    {
       ....
    }

has to be declared in public static class of your application. 必须在您的应用程序的public static类中声明。 Like, for example: 比如,例如:

public static class Extensions {


        public static XDocument GetXDocument(this OpenXmlPart part)
        {
          ....
        }
}

By writing this OpenXmlPart you specify an ExtensionMethod . 通过编写this OpenXmlPart您可以指定ExtensionMethod This is another, "fancy" way, to implement Decorator pattern in .NET application. 这是另一种“花哨”的方式,用于在.NET应用程序中实现Decorator模式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM