StefH / ProxyInterfaceSourceGenerator

This project uses Source Generation to generate an interface and a Proxy class for classes. This makes it possible to wrap external classes which do not have an interface, in a Proxy class which makes it easier to Mock and use Dependency Injection.
MIT License
39 stars 6 forks source link
code-generation

ProxyInterfaceGenerator

This project uses Source Generation to generate an interface and a Proxy class for classes. This makes it possible to wrap external classes which do not have an interface, in a Proxy class which makes it easier to Mock and use DI.

It supports:

NuGet

NuGet Badge

Usage

Given: an external existing class which does not implement an interface

public sealed class Person
{
    public string Name { get; set; }

    public string HelloWorld(string name)
    {
        return $"Hello {name} !";
    }
}

Create a partial interface

And annotate this with ProxyInterfaceGenerator.Proxy[...] and with the Type which needs to be wrapped:

[ProxyInterfaceGenerator.Proxy(typeof(Person))]
public partial interface IPerson
{
}

ProxyBaseClasses

In case also want to proxy the properties/methods/events from the base class(es), use this:

[ProxyInterfaceGenerator.Proxy(typeof(Person), true)] // πŸ‘ˆ Provide `true` as second parameter.
public partial interface IPerson
{
}

ProxyClassAccessibility

By default, the generated Proxy class is public. If you want to create the Proxy class as internal, use the following:

[ProxyInterfaceGenerator.Proxy(typeof(Person), ProxyClassAccessibility.Internal)] // πŸ‘ˆ Provide `ProxyClassAccessibility.Internal` as second parameter.
public partial interface IPerson
{
}

When the code is compiled, this source generator creates the following

:one: An additional partial interface

Which defines the same properties and methods as in the external class.

public partial interface IPerson
{
    string Name { get; set; }

    string HelloWorld(string name);
}

:two: A Proxy class

Which takes the external class in the constructor and wraps all public properties, events and methods.

// ⭐
public class PersonProxy : IPerson
{
    public Person _Instance { get; }

    public PersonProxy(Person instance)
    {
        _Instance = instance;
    }

    public string Name { get => _Instance.Name; set => _Instance.Name = value; }

    public string HelloWorld(string name)
    {
        string name_ = name;
        var result_19479959 = _Instance.HelloWorld(name_);
        return result_19479959;
    }
}

:star: By default the accessibility from the generated Proxy class is public.

:three: Use it

IPerson p = new PersonProxy(new Person());
p.Name = "test";
p.HelloWorld("stef");

Extra functionality

Ignore members

You can ignore members by adding a property to the membersToIgnore string array.

Example when you want to ignore the Postcode property:

[Proxy(typeof(Address), ["Postcode"])]
public partial interface IAddress
{
}

Note that's also possible to use wildcard matching to ignore multiple members at once.

[Proxy(typeof(Address), ["Post*"])]
public partial interface IAddress
{
}

References