Home > database >  Using Generics for Code Customization : C#
Using Generics for Code Customization : C#

Time:09-21

Trying to use Generics for code optimization. The program works however, due to redundant lines of code, I thought to try Generics once and check if the number of lines of codes can be reduced. I'd appreciate your help and feedbacks.

The error is type does not contain definition of Document

Print.cs

public class Print
    {
        public async Task<ResponseData> Get(Payload payload)
        {
            var FilePath = "";
            try
            {
                MemoryStream memstream = new MemoryStream();     
                    if (payload?.Type?.ToLower() == "consolidated")
                    {
                        if (payload?.Month?.ToLower() == "july" || payload?.Year == "2022")
                        {
                            if (payload?.date != "")
                            {
                                if (payload?.PageID?.IndexOf(",") > -1)
                                {
                                    AReport aReport = Adjustments.FillAReport(payload);
                                    PdfExport pdf = new PdfExport();
                                    FilePath = $"{Guid.NewGuid()}.pdf";
                                    pdf.Export(aReport.Document, filePath);
                                }
                                else
                                {
                                    BReport bReport = Adjustments.FillBReport(payload, true);
                                    PdfExport pdf = new PdfExport();
                                    FilePath = $"{Guid.NewGuid()}.pdf";
                                    pdf.Export(bReport.Document, FilePath);
                                }
                            }
                            else
                            {
                                CReport cReport = Adjustments.FillCReport(payload);
                                PdfExport pdf = new PdfExport();
                                FilePath = $"{Guid.NewGuid()}.pdf";
                                pdf.Export(cReport.Document, FilePath);
                            }
                        }
                    }
                    else
                    {
                        BReport bReport = Adjustments.FillBReport(payload, false);
                        PdfExport pdf = new PdfExport();
                        FilePath = $"{Guid.NewGuid()}.pdf";
                        pdf.Export(bReport.Document, FilePath);
                        
                    }

            }

Trying to Use Generics here. After Export is completed, I am trying to return back PDF file generated.

if (payload?.PageID?.IndexOf(",") > -1)
{
    AReport aReport = Adjustments.FillAReport(payload);
    FilePath = Generics.ExportContent<AReport>(aReport )
}
else
{
    BReport bReport = Adjustments.FillBReport(payload, true);
    FilePath = Generics.ExportContent<BReport>(bReport)
}

Generics.cs

public static string ExportContent<T>(this T type)
 {
    PdfExport pdf = new PdfExport();
    FilePath = $"{Guid.NewGuid()}.pdf";
    pdf.Export(type.Document, FilePath); //Error
    return FilePath;
 }

CodePudding user response:

An explanation of the error you're seeing might help clarify what generics are for or how they work.

public static string ExportContent<T>(this T input) // Changed the argument name for clarity
 {
    PdfExport pdf = new PdfExport();
    FilePath = $"{Guid.NewGuid()}.pdf";
    pdf.Export(input.Document, FilePath); //Error
    return FilePath;
 }

What is the type of input? The answer is that it can be anything. It depends on the caller.

If someone calls ExportContent<string>(someString) then when this executes, the type is string.

If they call ExportContent<SomeOtherClass>(whatever) then when this executes the type is SomeOtherClass.

Within this method, the compiler doesn't know what T will be. It might be anything, depending on the caller.

The error is because you're trying to use the input.Document property. But since the compiler doesn't know what type input is, it doesn't know if there is a Document property. If input is a string, there is no Document property.

The compiler is protecting you. It doesn't want you to wait until the code runs and you call the method, and then figure out if there's a Document property and throw an exception if there's not. It's better to be able to see the error and fix it when trying to compile the program instead of having it happen unexpectedly when you run the program.

What you're trying to do with the generic argument makes sense if you have different types of objects that implement the same interface or inherit from the same base class, and they all have that same Document property.

For example, suppose all of the objects you might pass to the method inherit from this base class:

public class MyBaseClass
{
    public string Document { get; set; } // Guessing that it's a string. I don't know
}

Then you could add a &generic constraint* to your method declaration, like this:

public static string ExportContent<T>(this T input) where T : MyBaseClass
{

Now T can't be just anything. It has to be either MyBaseClass or something that inherits from it. Then it will compile because it's guaranteed that the Document property will always exist.

Here's the twist: For the way you're using it, you don't need generics.

You could just do this:

public static string ExportContent(this MyBaseClass input) where T : MyBaseClass
{

...and you can still pass any argument that is of type MyBaseClass or inherits from it. The same works if you use an interface instead of a base class. You can pass any object that implements the interface.

  • Related