GithubHelp home page GithubHelp logo

revit.dependencyinjection's Introduction

Revit Dependency Injection

This repository borrows heavily from Onbox framework to create dependency inject with Revit Plugins. Instead of using custom container created by Onbox Team this is using Unity Container.

I've removed some libraries and utilities (like their mvc like packages). Packed all of it into a single dll for simplicity.

Installation

The package can be downloaded from Nuget

Application

Make sure that the application class that would normally inherit from IExternalApplication inherits from Revit App

[ContainerProvider("{{GUID}}")] // This attribute is crucial
public class App : RevitApp
{
	public override void OnCreateRibbon(IRibbonManager  ribbonManager)
	{
		// Here you can create Ribbon tabs, panels and buttons
	}
	public override Result OnStartup(IUnityContainer container,  UIControlledApplication application)
	{
		// Add Container registrations here
    
		return Result.Succeeded;
	}
	public override Result OnShutdown(IUnityContainer container, UIControlledApplication application)
	{
		// The container will be disposed automatically
    
		return Result.Succeeded;
	}
}

Command

Make sure that the command class that would normally inherit from IExternalCommand inherits RevitAppCommand<App> where "App" refers to the application class

[Transaction(TransactionMode.Manual)] // Important to every command
public class SampleCommand : RevitAppCommand<App>
{
	public override Result Execute(IUnityContainer container, ExternalCommandData commandData, 
                                 ref string message, ElementSet elements)
	{
		// Your logic here
	}
}

Container Registration

Registration follows standard Unity procedures below just the basics from their documentation.

Instance Registration

var instance = new Service();
container.RegisterInstance(instance);

// Named Registration
container.RegisterInstance("UniqueName", instance);

// Mapped to type
container.RegisterInstance<IService>(instance);
container.RegisterInstance<IService>("UniqueName", instance);
or
container.RegisterInstance(typeof(IService), instance)
container.RegisterInstance(typeof(IService), "UniqueName", instance)

Lifetime

// Per container (Default)
container.RegisterInstance("UniqueName", instance, InstanceLifetime.PerContainer);
container.RegisterInstance<IService>("UniqueName", instance, InstanceLifetime.PerContainer);

// Singleton
container.RegisterInstance("UniqueName", instance, InstanceLifetime.Singleton);
container.RegisterInstance<IService>("UniqueName", instance, InstanceLifetime.Singleton);

// External (Unity will not control the instance lifetime)
container.RegisterInstance<IService>("Some Name", instance, InstanceLifetime.External);

Factory Registration

container.RegisterFactory<IService>(f => new Service());

Type Registration

// Standard
container.RegisterType<IService, Service>();

// Named
container.RegisterType<IService, MailService>("Email");

// Lifetime
container.RegisterType<IService, MailService>("Email", TypeLifetime.Singleton);

You can either register required services directly in the OnStartup method

Or create extension methods

public static class SamplePipeline
{
	public static IUnityContainer RegisterSampleServices(this IUnityContainer container)
	{
		container.RegisterType<IService, Service>();
		return container;
	}
}

public class App : RevitApp
{
	[...]
	public override Result OnStartup(IUnityContainer container,  UIControlledApplication application)
	{
		// Direct
		container.RegisterType<IService, Service>();
		// Extension
		container.RegisterSampleServices();
		...
		return Result.Succeeded;
	}
	[...]
}

Resolving

For more detailed explanation refer to Unity Documentation

Generally speaking you can get instance of a class/service by

var instance = Container.Resolve<Service>();

Unity framework should automatically resolve services required by a constructor of a class

  • static constructors are not supported
  • private and protected constructors are not accessible
  • Constructors with ref and out parameters are not supported

Constructors are selected as below:

  • If present, use registered Injection Constructor
  • If present, annotated with an attribute
  • Automatically select constructor
    • Get all accessible constructors
    • Process constructors in ascending order from most complex to the default
      • Filter out restricted constructors
      • Loop through parameters and check if
        • Is primitive
          • Is registered with the container
          • Has default value
        • Is resolvable type
        • Is registered with container
      • Select the first constructor the container can create

Sample

// Default
public class Service
{
	private  readonly  IDependency _dependency;
	
	public Service(IDependency dependency)
	{
		_dependency = dependency;
	}
}

// Constructor Annotation
public class Service
{
	private  readonly  IDependency _dependency;
	
	[InjectionConstructor]
	public Service(IDependency dependency)
	{
		_dependency = dependency;
	}
	
	public Service()
	{
	}
}

// Or Registering a specific constructor
Container.RegisterType<Service>(Invoke.Constructor());

Project Template

For convenience I've created a project templates

revit.dependencyinjection's People

Contributors

coolicky avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.