DesignPatternCodeGenerator 1.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package DesignPatternCodeGenerator --version 1.0.0
NuGet\Install-Package DesignPatternCodeGenerator -Version 1.0.0
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="DesignPatternCodeGenerator" Version="1.0.0" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add DesignPatternCodeGenerator --version 1.0.0
#r "nuget: DesignPatternCodeGenerator, 1.0.0"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install DesignPatternCodeGenerator as a Cake Addin
#addin nuget:?package=DesignPatternCodeGenerator&version=1.0.0

// Install DesignPatternCodeGenerator as a Cake Tool
#tool nuget:?package=DesignPatternCodeGenerator&version=1.0.0

DesignPatternCodeGenerator

The library is used to generate the code of typical design patterns in C #, based on the capabilities of the .NET Compiler Platform SDK (Roslyn APIs). More information about Roslyn APIs: https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/

How to start using the library?

Edit your project and add the following, replacing the project path with the one from the .NET Standard project you created above:

  <ItemGroup>
	<ProjectReference Include="..\PathTo\DesignPatternCodeGenerator.csproj"
					  OutputItemType="Analyzer"
					  ReferenceOutputAssembly="true" />
        <ProjectReference Include="..\PathTo\DesignPatternCodeGenerator.csproj" />
  </ItemGroup>

The generated files can be seen in the project tree:

Dependencies → Analyzers →

image

Container IoC

The container IoC is genereted based on one attribute:

  • [Container("ContainerName", ObjectLifeTime, new string[] { "ExcludedInterface1", "ExcludedInterface2" })]

or

  • [Container("ContainerName", ObjectLifeTime)]
using DesignPatternCodeGenerator.Attributes.ContainerIoC;

namespace Samples.ContainerIoC;

interface IViewModel1
{
}

interface IViewModel2
{
}

interface IViewModel3 : IViewModel2
{
}

interface IViewModel4
{
}

[Container("AddViewModels", ObjectLifeTime.Singleton, new string[] { "IViewModel4" })]
public class MainViewModel : IViewModel1, IViewModel3, IViewModel4, IDisposable
{
    public void Dispose()
    {
    }
}

[Container("AddViewModels", ObjectLifeTime.Transient)]
public class ViewModel : IViewModel1
{
}

[Container("AddViewModels", ObjectLifeTime.Scoped, new string[] { "IViewModel4", "IViewModel1" })]
public class MainViewModelExtension : MainViewModel
{
}

Using the code above, the generator will generate a container.

// <auto-generated/>
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using DesignPatternCodeGenerator.Attributes.ContainerIoC;

namespace Samples.ContainerIoC
{
    public static class AddViewModelsHostBuildersExtension
    {
    	public static IHostBuilder AddViewModels(this IHostBuilder host)
        {
	    host.ConfigureServices(services =>
	    {
	        services.AddSingleton<IViewModel1, MainViewModel>();
		services.AddSingleton<IViewModel3, MainViewModel>();
		services.AddSingleton<IViewModel2, MainViewModel>();
		services.AddTransient<IViewModel1, ViewModel>();
		services.AddScoped<IViewModel3, MainViewModelExtension>();
		services.AddScoped<IViewModel2, MainViewModelExtension>();
	    });
	    
	    return host;
	}
    }
}

Facade

The facade pattern is genereted based on three attributes:

  • [FacadeMethod("FacadeMethodName")] - this attribute should be applied to the method that is about to become a facade method,
  • [FacadeMainParameter("FacadeMethodParameter")] - this attribute should be applied to the facade method parameter,
  • [FacadeParameter("ClassName.MethodName")] - this parameter should be applied to the parameter, and in the constructor it takes the method path.
using DesignPatternCodeGenerator.Attributes.Facade;

namespace Samples.Facade;

public class DependencyScanner
{
    [FacadeMethod("Scan")]
    public IEnumerable<string> DependencyScan([FacadeMainParameter("githubUrl")]string githubUrl)
    {
        Console.WriteLine("Dependency Scan");

        return new List<string>() { "Dependency Error1" };
    }
}

public class QualityScanner
{
    [FacadeMethod("Scan")]
    public IEnumerable<string> QualityScan([FacadeMainParameter("githubUrl")] string githubUrl)
    {
        Console.WriteLine("Quality scan");

        return new List<string>() { "Error1", "Error2" };
    }
}

public class SecurityScanner
{
    [FacadeMethod("Scan")]
    public IEnumerable<string> SecurityScan([FacadeMainParameter("githubUrl")] string githubUrl)
    {
        Console.WriteLine("Security scan");

        return new List<string>() { "Security Error1" };
    }
}

public class ReportGenerator
{
    [FacadeMethod("Scan")]
    public void GenerateReport(
        [FacadeParameter("QualityScanner.QualityScan")] IEnumerable<string> qualityScanErrors,
        [FacadeParameter("SecurityScanner.SecurityScan")] IEnumerable<string> securityScanErrors,
        [FacadeParameter("DependencyScanner.DependencyScan")] IEnumerable<string> dependencyScanErrors)
    {
        Console.WriteLine("Quality Scan Errors:");
        Console.WriteLine(string.Join(", ", qualityScanErrors));

        Console.WriteLine("Security Scan Errors:");
        Console.WriteLine(string.Join(", ", securityScanErrors));

        Console.WriteLine("Dependency Scan Errors:");
        Console.WriteLine(string.Join(", ", dependencyScanErrors));
    }
}

Using the code above, the generator will generate a facade.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.Facade;

namespace Samples.Facade
{
    public class ScanFacade
    {
        private QualityScanner _qualityScanner = new QualityScanner();
	private SecurityScanner _securityScanner = new SecurityScanner();
	private DependencyScanner _dependencyScanner = new DependencyScanner();
	private ReportGenerator _reportGenerator = new ReportGenerator();

        public void Scan(string githubUrl)
        {
            var qualityScannerQualityScan = _qualityScanner.QualityScan(githubUrl);
	    var securityScannerSecurityScan = _securityScanner.SecurityScan(githubUrl);
	    var dependencyScannerDependencyScan = _dependencyScanner.DependencyScan(githubUrl);
	    
	    _reportGenerator.GenerateReport(qualityScannerQualityScan, securityScannerSecurityScan, dependencyScannerDependencyScan);
        }
    }
}

Prototype

The prototype pattern is genereted based on one attribute:

  • Prototype - this attribute should be applied to the class that is about to become a prototype. The class must be a partial class.

Example:

using DesignPatternCodeGenerator.Attributes.Prototype;

namespace Samples.Prototype;

[Prototype]
public partial class Person
{
    public string? Name { get; set; }
    public string? LastName { get; set; }
    public Address? PersonAddress { get; set; }
    public Contacts? PersonContacts { get; set; }
}

public class Address
{
    public string? HouseNumber { get; set; }
    public string? Street { get; set; }
    public string? City { get; set; }
}

public class Contacts
{
    public string? PhoneNumber { get; set; }
    public string? Email { get; set; }
}

Using the code above, the generator will generate a partial class with an implemented prototype with the ShallowCopy() and DeepCopy() methods.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.Prototype;

namespace Samples.Prototype
{
    public partial class Person
    {
        public Person ShallowCopy()
        {
            return (Person)this.MemberwiseClone();
        }

        public Person DeepCopy()
        {
            Person clone = (Person)this.MemberwiseClone();

            clone.PersonAddress = new Address()
            {
	    	HouseNumber = PersonAddress.HouseNumber,
		Street = PersonAddress.Street,
		City = PersonAddress.City
            };

	    clone.PersonContacts = new Contacts()
            {
	    	PhoneNumber = PersonContacts.PhoneNumber,
		Email = PersonContacts.Email
            };

            return clone;
        }
    }
}

AbstractFactory

The abstract factory pattern is generated based on two attributes:

  • [AbstractFactory("MainInterfaceName")] - this attribute should be appiled to interface,
  • [AbstractFactoryClass("FactoryClassName")] - this attribute should be appiled to class.

Example:

using DesignPatternCodeGenerator.Attributes.AbstractFactory;

namespace Samples.AbstractFactory;

[AbstractFactory("UIElement")]
public interface IButton
{
    void Render();
    void HandleClick();
}

[AbstractFactoryClass("Windows")]
public class WindowsButton : IButton
{
    public void HandleClick()
    {
        Console.WriteLine("Handle windows click event");
    }

    public void Render()
    {
        Console.WriteLine("Render windows button");
    }
}

[AbstractFactoryClass("Mac")]
public class MacButton : IButton
{
    public void HandleClick()
    {
        Console.WriteLine("Handle mac click event");
    }

    public void Render()
    {
        Console.WriteLine("Render mac button");
    }
}
using DesignPatternCodeGenerator.Attributes.AbstractFactory;

namespace Samples.AbstractFactory;

[AbstractFactory("UIElement")]
public interface ITextBox
{
    void Render();
    void HandleInput();
}

[AbstractFactoryClass("Windows")]
public class WindowsTextBox : ITextBox
{
    public void HandleInput()
    {
        Console.WriteLine("Handle windows text input");
    }

    public void Render()
    {
        Console.WriteLine("Render windows textbox");
    }
}

[AbstractFactoryClass("Mac")]
public class MacTextBox : ITextBox
{
    public void HandleInput()
    {
        Console.WriteLine("Handle mac text input");
    }

    public void Render()
    {
        Console.WriteLine("Render mac textbox");
    }
}

Using the code above, the generator will generate an abstract factory which consists of a main factory interface and factory classes.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.AbstractFactory;

namespace Samples.AbstractFactory
{
    public interface IUIElementFactory
    {
    	ITextBox CreateTextBox();
	IButton CreateButton();
    }
}
// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.AbstractFactory;

namespace Samples.AbstractFactory
{
    public class WindowsFactory : IUIElementFactory
    {
        
        public ITextBox CreateTextBox()
        {
            return new WindowsTextBox();
        }

        public IButton CreateButton()
        {
            return new WindowsButton();
        }
    }
}
// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.AbstractFactory;

namespace Samples.AbstractFactory
{
    public class MacFactory : IUIElementFactory
    {
        
        public ITextBox CreateTextBox()
        {
            return new MacTextBox();
        }

        public IButton CreateButton()
        {
            return new MacButton();
        }
    }
}

Factory

The factory pattern is generated based on three attributes:

  • Factory - this attribute should be applied to the main interface,
  • [Parameter] - this attribute should be applied to the property that is to be provided when creating individual objects,
  • [FactoryChild] - this attribute should be applied to the class that implements the main interface.

Example:

using DesignPatternCodeGenerator.Attributes;
using DesignPatternCodeGenerator.Attributes.Factory;

namespace Samples.Factory;
[Factory]
public interface ICar
{
    [Parameter]
    public string Name { get; set; }        
    public int HorsePower { get; set; }

}

[FactoryChild]
class Bmw : ICar
{
    public string Name { get; set; }
    public int HorsePower { get; set; }

    public Bmw(string name, int horsePower)
    {
        Name = name;
        HorsePower = horsePower;
    }
}

[FactoryChild]
partial class Audi : ICar
{
    public string Name { get; set; }
    public int HorsePower { get; set; }

    public Audi(string name, int horsePower)
    {
        Name = name;
        HorsePower = horsePower;
    }
}

Using the code above, the generator will generate a factory which consists of a factory interface, a factory class, and an enum type.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes;
using DesignPatternCodeGenerator.Attributes.Factory;

namespace Samples.Factory
{
    public interface ICarFactory
    {
        public ICar Create(CarFactoryType type,string Name);
    }
}
// <auto-generated/>
using DesignPatternCodeGenerator.Attributes;
using DesignPatternCodeGenerator.Attributes.Factory;

namespace Samples.Factory
{
    public class CarFactory: ICarFactory
    {
        private readonly int _horsepower;
        
        public CarFactory(int HorsePower)
        {
            _horsepower = HorsePower;
        }
        
        public ICar Create(CarFactoryType type,string Name)
        {
          switch (type)
          {
              case CarFactoryType.Bmw :
                  return new Bmw(Name, _horsepower);
               case CarFactoryType.Audi :
                  return new Audi(Name, _horsepower);
               default :
                  throw new Exception($"Type {type} is not handled");
            }    
        }
    }
}
// <auto-generated/>
using DesignPatternCodeGenerator.Attributes;
using DesignPatternCodeGenerator.Attributes.Factory;

namespace Samples.Factory
{
    public enum CarFactoryType
    {
        Bmw,
        Audi,
    }
}

Null Object

The null object pattern is generated based on only one attribute:

  • [NullObject] - this attribute should be applied to the interface.
[NullObject]
public interface ILog
{
    public int Id { get; }
    public string Login(string username, string password);
    public void Info(string message);
    public void Warn(string message);
}

Using the code above, the generator will generate a class with the null object implemented.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.NullObject;

namespace Samples.NullObject
{
    public class LogNullObject : ILog
    {
    	public int Id { get; }

	public void Info(string message) { }
	public void Warn(string message) { }
	public string Login(string username, string password) 
        {
	    return default(string);
        }
    }
}

Singleton

The singleton pattern is generated based on only one attribute:

  • Singleton - this attribute should be applied to the class that is about to become a singleton. The class must be a partial class.

Example

[Singleton]
public partial class Configuration
{
    public string SomeProperty { get; set; }
}

Using the code above, the generator will generate a partial class with the singleton implemented.

// <auto-generated/>
using DesignPatternCodeGenerator.Attributes.Singleton;

namespace Samples.Singleton
{
    public partial class Configuration
    {
    	private static Configuration _instance = null;
	private static object obj = new object();
	
	private Configuration() { }
	
	public static Configuration GetInstance()
	{
            lock(obj)
            {
                if (_instance == null)
                {
                    _instance = new Configuration();
                }
            }

        return _instance;
        }
    }
}
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.0.4 362 1/15/2023
1.0.3 321 1/12/2023
1.0.2 130 1/12/2023
1.0.1 126 1/12/2023
1.0.0 131 1/12/2023