{"id":790,"date":"2025-06-30T19:06:37","date_gmt":"2025-06-30T19:06:37","guid":{"rendered":"https:\/\/docs.sisus.co\/init-args\/?p=790"},"modified":"2025-07-14T19:26:39","modified_gmt":"2025-07-14T19:26:39","slug":"generic-services","status":"publish","type":"post","link":"https:\/\/docs.sisus.co\/init-args\/advanced\/generic-services\/","title":{"rendered":"Generic Services"},"content":{"rendered":"<p>Types that contain generic type parameters can also be registered as <a href=\"https:\/\/docs.sisus.co\/init-args\/reference\/global-services\/\">global services<\/a> by adding the <a href=\"https:\/\/docs.sisus.co\/init-args\/services\/service-attribute\/\">[Service] attribute<\/a> to them:<\/p>\n<pre>using Sisus.Init;\r\n\r\n[Service]\r\npublic class Logger&lt;T&gt;\r\n{\r\n    public void Info(string message) =&gt; Debug.Log(typeof(T).Name + \" - \" + message);\r\n}<\/pre>\n<p>When this is done, no instance of the global service is created automatically during initialization &#8211; even if you do not set <em>LazyInit<\/em> to\u00a0<em>true <\/em>on the [Service] attribute. Instead, an instance will only be created lazily at the moment when the first <a href=\"https:\/\/docs.sisus.co\/init-args\/clients\/\">client<\/a> that depends on it is being initialized:<\/p>\n<pre>using Sisus.Init;\r\nusing UnityEngine;\r\n\r\npublic class Client : MonoBehaviour&lt;Logger&lt;Client&gt;&gt;\r\n{\r\n    \/\/ The Logger&lt;Client&gt; object gets created when the first Client component is being loaded\r\n    protected override void Init(Logger&lt;Client&gt; logger) =&gt; logger.Info(\"Hello, World!\");\r\n}<\/pre>\n<p>If multiple clients depend on the global service, but with different generic type arguments, then a new global service instance is created for each different variation that is requested by a client (e.g. <em>Logger&lt;Client1&gt;,<\/em> <em>Logger&lt;Client2&gt;<\/em> etc.).<\/p>\n<p>It is also possible to register the service using a generic interface as its defining type:<\/p>\n<pre>using Sisus.Init;\r\n\r\n[Service(ILogger&lt;&gt;)]\r\npublic class Logger&lt;T&gt; : ILogger&lt;T&gt;\r\n{\r\n    public void Info(string message) =&gt; Debug.Log(typeof(T).Name + \" - \" + message);\r\n}<\/pre>\n<p>Then clients can depend on the interface type instead of the concrete type of the service:<\/p>\n<pre>using Sisus.Init;\r\nusing UnityEngine;\r\n\r\npublic class Client : MonoBehaviour&lt;ILogger&lt;Client&gt;&gt;\r\n{\r\n    protected override void Init(ILogger&lt;Client&gt; logger) =&gt; logger.Info(\"Hello, World!\");\r\n}<\/pre>\n<p>If you can&#8217;t (or don&#8217;t want to) add the [Service] attribute to the generic type directly &#8211; for example, because it&#8217;s part of a third-party package &#8211; then you can define a service initializer with a generic type parameter and add the [Service] attribute to it instead. Init(args) can lazily determine the generic type argument for the service initializer based on the service type that is being requested by a client.<\/p>\n<p>Here is an example of how <a href=\"https:\/\/github.com\/Cysharp\/ZLogger\">ZLogger<\/a> could be registered as your global logging service using a generic service initializer:<\/p>\n<pre>using Microsoft.Extensions.Logging;\r\nusing Sisus.Init;\r\nusing UnityEngine;\r\nusing ZLogger.Unity;\r\n\r\n[Service(typeof(ILogger&lt;&gt;))]\r\nsealed class ZLoggerInitializer&lt;T&gt; : ServiceInitializer&lt;ILogger&lt;T&gt;&gt;\r\n{\r\n    public override ILogger&lt;T&gt; InitTarget()\r\n    {\r\n        var factory = LoggerFactory.Create(configure =&gt;\r\n        {\r\n            configure.SetMinimumLevel(LogLevel.Trace);\r\n            configure.AddZLoggerUnityDebug();\r\n        });\r\n\r\n        return factory.CreateLogger&lt;T&gt;();\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Types that contain generic type parameters can also be registered as global services by adding the [Service] attribute to them: using Sisus.Init; [Service] public class Logger&lt;T&gt; { public void Info(string message) =&gt; Debug.Log(typeof(T).Name + &#8221; &#8211; &#8221; + message); } When this is done, no instance of the global service is created automatically during initialization ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"https:\/\/docs.sisus.co\/init-args\/advanced\/generic-services\/\" title=\"read more\">Read more<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/790"}],"collection":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/comments?post=790"}],"version-history":[{"count":2,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/790\/revisions"}],"predecessor-version":[{"id":792,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/790\/revisions\/792"}],"wp:attachment":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/media?parent=790"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/categories?post=790"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/tags?post=790"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}