hadashia / vcontainer Goto Github PK
View Code? Open in Web Editor NEWThe extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine.
Home Page: https://vcontainer.hadashikick.jp
License: MIT License
The extra fast, minimum code size, GC-free DI (Dependency Injection) library running on Unity Game Engine.
Home Page: https://vcontainer.hadashikick.jp
License: MIT License
I'm trying to use VContainer to inject dependencies into nested objects that are not derived from MonoBehaviour
. Here's what I mean.
Suppose I represent my game logic in systems like so:
public sealed class PhysicsSystem : IExecuteSystem
{
private readonly IPhysicsService _physics;
private readonly ITimeService _time;
private readonly IPhysicsConfig _physicsConfig;
public PhysicsSystem(IPhysicsService physics, ITimeService time, IPhysicsConfig physicsConfig)
{
// Initialization
}
public void Execute()
{
// Logic goes here
}
}
I have dozens of these systems, nearly all of which depend on some common services or configuration objects. To keep my code manageable, I group them in System
-like objects called Feature
s. This results in a logical tree-like structure. Here's an example:
public sealed class GameplayFeature : Feature
{
public GameplayFeature()
{
Add(new PhysicsSystem(/* ... */));
Add(new AiFeature(/* ... */));
}
}
Note that the order in which these systems are declared and added is important.
The naive thing would be to register every System
and Feature
, with the top-most Feature
-- let's call it FullGameFeature
-- having an enormous constructor that passes in every possible dependency in my game. This is not feasible.
So what would you suggest? My requirements are:
Feature
's System
s within its constructorSystem
s and Feature
sOne thing I won't do is to inject the IObjectResolver
into all Feature
s and System
s, as my current home-grown dependency injection framework already does something similar to that. If VContainer requires me to do this, then there will be no advantage in adopting it.
Mono.Cecil is missing from unity package. Nuget version https://www.nuget.org/packages/Mono.Cecil/ works fine.
Hi. Is there a way to register int or float instances?
The long README has usability problems, so I would like to consider creating a website.
sorry my english,i use google translate
This sometimes happens in projects. I need to create a class and inject property, and assign the class to a local variable.
That's all I can do now.
public class A
{
[Inject] private string B;
public A()
{
}
}
public class B
{
public B()
{
var C = new A();
xxx.Inject(C);
C........
}
}
I would like to have a method similar to the Instantiate method in Zenject.
That way I can put variables in the constructor. And it would be much smoother to write
このようなコンポーネントを作り、ICameraRigをinjectしています
// 実行時にparentを変更するだけのスクリプト
public class ParentToTrackingPoint : MonoBehaviour
{
ICameraRig cameraRig;
[Inject]
public void Construct(ICameraRig cameraRig)
{
this.cameraRig = cameraRig;
Debug.Log(cameraRig);
}
[SerializeField]
private TrackingPoint trackingPoint;
// Start is called before the first frame update
void Start()
{
Debug.Log(cameraRig);
var t = cameraRig.GetTransform(trackingPoint);
transform.SetParent(t, false);
}
}
configure
builder.RegisterEntryPoint<OculusCameraRig>(Lifetime.Singleton); //ICameraRigの実装
builder.RegisterComponentInHierarchy<ParentToTrackingPoint>();
このとき、ヒエラルキー上でこのコンポーネントを持つオブジェクトが複数ある場合、最初の一つのみにinjectされているようです。
ヒエラルキー上で2つのオブジェクトの順番を入れ替えると、最初の方のみが正しく動いています。
これはバグでしょうか?それとも私のDIに関する勘違いでしょうか?(当方Unityのプログラミングに慣れていないため勘違いであったら申し訳ないです)
I want to register all the types I need that derive from a certain interface, and there's no way to do this:
var baseType = typeof(IUseCase);
var assembly = baseType.Assembly;
var useCaseTypes = assembly.GetTypes()
.Where(t => baseType.IsAssignableFrom(t));
foreach (var useCaseType in useCaseTypes)
{
builder.Register(useCaseType, Lifetime.Transient);
}
Hello! Just started using VContainer and liking it, but I have a problem and can't figure out the solution. I want to create a factory that creates instances of some base class but resolves the dependencies of its descendants. Here is the example:
public class ScreenService
{
private Dictionary<string, ScreenBase> _screenPrefabs;
// this is the subject of question
private SomeMagicFactory _someMagicFactory;
public void Show(string screenName)
{
_someMagicFactory.Instatiate(_screenPrefabs[screenName]);
}
// some other code
}
public abstract class ScreenBase: MonoBehaviour
{
// some base class code
}
public class LoginScreen : ScreenBase
{
private ILoginService _loginService;
[Inject]
public void Construct(ILoginService loginService)
{
_loginService = loginService;
}
// some login screen specific code that uses ILoginService
}
public class SomeOtherScreen : ScreenBase
{
private ISomeService _someService;
[Inject]
public void Construct(ISomeService someService)
{
_someService = someService;
}
// some screen code
}
With the current factory approach in VContainer I can't use one factory to instantiate/resolve dependencies at runtime in classes inherited from ScreenBase
, because that would require me to create different factory for each class that inherits ScreenBase
.
In Zenject, e.g. creating that sort of factory is pretty easy:
public class Factory : PlaceholderFactory<UnityEngine.Object, ScreenBase>
{
}
And this factory will resolve all dependencies of classes that inherit from ScreenBase
automatically.
It also will resolve dependencies not only on direct descendant of ScreenBase
, but dependencies of all MonoBehaviour classes with [Inject] attribute on target GameObject. But thats out of question, nice feature, but not required at all.
Is it possible to achieve desired behaviour with VContainer?
Assets/
└ Scenes/
└ SampleScene.unity
└ Foo.cs
public class Foo { }
See below for the English version.
この一連の流れによって、StackOverflowExceptionが起きてから無限にNullReferenceExceptionが表示されるようになります。
コードをAssembly-CSharp以外のasmdefに収めることで解消します。
エラーが出ている間はTest Runnerがテストケースを読んでくれない状態になるため、Test Runnerが使えないという状態です。
バグなのかどうか、またバグだったとしてもVContainerのものなのか、TestRunnerのものなのかが掴めておらず申し訳ないのですが、確認していただければ幸いです。
This raises a StackOverflowException and an infinite NullReferenceExceptions.
If you compile the codes into another asmdef other than Assembly-CSharp, it works.
While the error is happening, Test Runner won't read your test cases, so you can't use Test Runner.
I don't know if this is a bug or expected, and even if it is, I don't know if it's a VContainer's or a TestRunner’s, so I would appreciate it if you could check.
StackOverflowException: The requested operation caused a stack overflow.
System.Globalization.CultureInfo.CreateCulture (System.String name, System.Boolean reference) (at :0)
System.Reflection.AssemblyName.FillName (Mono.MonoAssemblyName* native, System.String codeBase, System.Boolean addVersion, System.Boolean addPublickey, System.Boolean defaultToken, System.Boolean assemblyRef) (at :0)
System.Reflection.Assembly.GetReferencedAssemblies (System.Reflection.Assembly module) (at :0)
System.Reflection.MonoAssembly.GetReferencedAssemblies () (at :0)
UnityEditor.TestTools.TestRunner.EditorAssemblyWrapper.GetReferencedAssemblies () (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/EditorAssemblyWrapper.cs:13)
UnityEditor.TestTools.TestRunner.EditorLoadedTestAssemblyProvider.FilterAssemblyForTestReference (UnityEngine.TestTools.Utils.IAssemblyWrapper assemblyToFilter, UnityEngine.TestTools.Utils.IAssemblyWrapper[] loadedAssemblies, System.Collections.Generic.IDictionary2[TKey,TValue] filterResults) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/EditorLoadedTestAssemblyProvider.cs:86) UnityEditor.TestTools.TestRunner.EditorLoadedTestAssemblyProvider.FilterAssemblyForTestReference (UnityEngine.TestTools.Utils.IAssemblyWrapper assemblyToFilter, UnityEngine.TestTools.Utils.IAssemblyWrapper[] loadedAssemblies, System.Collections.Generic.IDictionary
2[TKey,TValue] filterResults) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/EditorLoadedTestAssemblyProvider.cs:101)
UnityEditor.TestTools.TestRunner.EditorLoadedTestAssemblyProvider.FilterAssemblyForTestReference (UnityEngine.TestTools.Utils.IAssemblyWrapper assemblyToFilter, UnityEngine.TestTools.Utils.IAssemblyWrapper[] loadedAssemblies, System.Collections.Generic.IDictionary2[TKey,TValue] filterResults) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/EditorLoadedTestAssemblyProvider.cs:101) UnityEditor.TestTools.TestRunner.EditorLoadedTestAssemblyProvider.FilterAssemblyForTestReference (UnityEngine.TestTools.Utils.IAssemblyWrapper assemblyToFilter, UnityEngine.TestTools.Utils.IAssemblyWrapper[] loadedAssemblies, System.Collections.Generic.IDictionary
2[TKey,TValue] filterResults) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/EditorLoadedTestAssemblyProvider.cs:101) < message truncated >
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.TestTools.TestRunner.GUI.TestTreeViewBuilder.ParseTestTree (System.Int32 depth, UnityEditor.IMGUI.Controls.TreeViewItem rootItem, UnityEditor.TestTools.TestRunner.Api.ITestAdaptor testElement) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/GUI/TestListBuilder/TestTreeViewBuilder.cs:54)
UnityEditor.TestTools.TestRunner.GUI.TestTreeViewBuilder.BuildTreeView (UnityEditor.TestTools.TestRunner.GUI.TestFilterSettings settings, System.Boolean sceneBased, System.String sceneName) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/GUI/TestListBuilder/TestTreeViewBuilder.cs:35)
UnityEditor.TestTools.TestRunner.GUI.TestListTreeViewDataSource.FetchData () (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/GUI/TestListTreeView/TestListTreeViewDataSource.cs:37)
UnityEditor.IMGUI.Controls.TreeViewDataSource.ReloadData () (at /Users/bokken/buildslave/unity/build/Editor/Mono/GUI/TreeView/TreeViewDataSource.cs:54)
UnityEditor.IMGUI.Controls.TreeViewController.ReloadData () (at /Users/bokken/buildslave/unity/build/Editor/Mono/GUI/TreeView/TreeViewController.cs:298)
UnityEditor.TestTools.TestRunner.GUI.TestListGUI.Reload () (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/GUI/Views/TestListGUIBase.cs:202)
UnityEditor.TestTools.TestRunner.TestRunnerWindow+<>c__DisplayClass27_0.b__0 (UnityEditor.TestTools.TestRunner.Api.ITestAdaptor rootTest) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunnerWindow.cs:162)
UnityEditor.TestTools.TestRunner.Api.TestRunnerApi+<>c__DisplayClass8_0.b__0 (UnityEditor.TestTools.TestRunner.Api.ITestAdaptor testRoot) (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/Api/TestRunnerApi.cs:143)
UnityEditor.TestTools.TestRunner.TestListJob.EditorUpdate () (at Library/PackageCache/[email protected]/UnityEditor.TestRunner/TestRunner/Utils/TestListJob.cs:31)
UnityEditor.EditorApplication.Internal_CallUpdateFunctions () (at /Users/bokken/buildslave/unity/build/Editor/Mono/EditorApplication.cs:327)
ver1.6.0現在、RegsiterInstanceで登録したインスタンスは全てLifetime.Scopedで管理されているようです。
それによってIDisposableを実装したインスタンスがLifetimeScopeごとにDisposeされてしまっています。
LifetimeScopeに親子関係を持たせる場合、子のLifetimeScopeが破棄されると親のLifetimeScopeでも登録したインスタンスがDisposeされた状態になるので困ってしまいます。
RegisterInstanceのタイミングでLifetimeも指定できるAPIがあると嬉しいです。
お世話になっております。
Unity 2021.2.0a13 (Windows)にて、 VContainer
並びに VContainer.EnableCodeGen
を Assembly Definition References
に追加した asmdef
があると次のエラーでビルドが失敗してしまうようになっておりました。
(0,0): error VContainer failed pre code gen for <Module> : Could not load file or assembly '該当のアセンブリ名, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'. General Exception (0x80131500)
最小の手順としては次になります。
asmdef
を作るAssembly Definition References
に VContainer
と VContainer.EnableCodeGen
を追加する(コード生成の対象にする)またこちらですが、手元では 2021.1.3f1
と 2021.2.0a10 ~ 13(10より前については確認していません……)
でも同様のエラーが発生しておりました( 2020.3.4f1
、2019.4.23f1
では問題なくビルドが通ります)
原因の特定までに至らなかったのですが、今後のバージョンアップの参考になればと思い報告させていただきます 🙇
Hello! I am trying to register class that has inheritance chain from several generic classes, like:
public ISomeInterface<T>{
}
public abstract class Base<T>: ISomeInterface<T>{
}
public abstract class AnotherBase<T>: Base<T>{
private readonly SomeDependency _dep;
protected AnotherBase(SomeDependency dep){
_dep = dep;
}
}
public class ActualClass: AnotherBase<ActualGenericClass>
{
public ActualClass(SomeDependency dep): base(dep){
}
}
SomeDependency
is a ScriptableObject
that is registered like this with builder.RegisterInstance(_dep);
.
The next line is builder.Register<ActualClass>(Lifetime.Singleton);
And that gives me that error on container resolve:
IndexOutOfRangeException: Index was outside the bounds of the array.
VContainer.Internal.CappedArrayPool`1[T].Rent (System.Int32 length) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/CappedArrayPool.cs:51)
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:31)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:44)
VContainer.Container+<>c__DisplayClass4_0.<.ctor>b__1 () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:132)
System.Lazy`1[T].CreateValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].LazyInitValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].get_Value () (at <9577ac7a62ef43179789031239ba8798>:0)
VContainer.Container.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:152)
VContainer.Container.Resolve (System.Type type) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:140)
VContainer.IObjectResolverExtensions.ResolveOrParameter (VContainer.IObjectResolver resolver, System.Type parameterType, System.String parameterName, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/IObjectResolverExtensions.cs:30)
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:39)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:44)
VContainer.Container.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:150)
VContainer.Internal.CollectionRegistration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:92)
VContainer.Container.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:150)
VContainer.Container.Resolve (System.Type type) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:140)
VContainer.IObjectResolverExtensions.ResolveOrParameter (VContainer.IObjectResolver resolver, System.Type parameterType, System.String parameterName, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/IObjectResolverExtensions.cs:30)
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:39)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:44)
VContainer.Container+<>c__DisplayClass4_0.<.ctor>b__1 () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:132)
System.Lazy`1[T].CreateValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].LazyInitValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].get_Value () (at <9577ac7a62ef43179789031239ba8798>:0)
VContainer.Container.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:152)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:68)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:74)
VContainer.ScopedContainer.Resolve (System.Type type) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:55)
VContainer.IObjectResolverExtensions.ResolveOrParameter (VContainer.IObjectResolver resolver, System.Type parameterType, System.String parameterName, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/IObjectResolverExtensions.cs:30)
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:39)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:44)
VContainer.ScopedContainer+<>c__DisplayClass10_0.<.ctor>b__1 () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:48)
System.Lazy`1[T].CreateValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].LazyInitValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].get_Value () (at <9577ac7a62ef43179789031239ba8798>:0)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:78)
VContainer.ScopedContainer.Resolve (System.Type type) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:55)
VContainer.IObjectResolverExtensions.ResolveOrParameter (VContainer.IObjectResolver resolver, System.Type parameterType, System.String parameterName, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/IObjectResolverExtensions.cs:30)
VContainer.Internal.ReflectionInjector.InjectMethods (System.Object obj, VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:99)
VContainer.Internal.ReflectionInjector.Inject (System.Object instance, VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:23)
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/ReflectionInjector.cs:50)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:44)
VContainer.ScopedContainer+<>c__DisplayClass10_0.<.ctor>b__1 () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:48)
System.Lazy`1[T].CreateValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].LazyInitValue () (at <9577ac7a62ef43179789031239ba8798>:0)
System.Lazy`1[T].get_Value () (at <9577ac7a62ef43179789031239ba8798>:0)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:78)
VContainer.Internal.CollectionRegistration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Internal/Registration.cs:92)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:63)
VContainer.ScopedContainer.Resolve (System.Type type) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Container.cs:55)
VContainer.IObjectResolverExtensions.Resolve[T] (VContainer.IObjectResolver resolver) (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/IObjectResolverExtensions.cs:8)
VContainer.Unity.LifetimeScope.ActivateEntryPoints () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Unity/LifetimeScope.cs:264)
VContainer.Unity.LifetimeScope.Build () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Unity/LifetimeScope.cs:162)
VContainer.Unity.LifetimeScope.Awake () (at Library/PackageCache/jp.hadashikick.vcontainer@8fd4963749/Runtime/Unity/LifetimeScope.cs:122)
Is it because of that inheritance chain with generics? How to avoid that error if I still want to use that generic base classes?
Hello! I've been playing with VContainer, and i can't find our how to make one thing.
I have some MonoBehaviours "presenters" that inserted into prefab and they need their model dependency. What is the proper way to do that? It there a way to inject dependencies into current class?
EDIT: I should add that in this is basically to support some legacy code. Currently i think best way it to save main LifetimeScope to some global variable and resolve using Lazy.
Assembly start with "Unity" and end with "CodeGen", for example "Unity.VContainer.CodeGen", is able to access unity's own ILPostProcessor
, so vcontainer could rid of redistribution of "Unity.CompilationPipeline.Common.dll".
Unityには、FieldInfo.SetValue
と同一の処理を数倍高速に実行できる UnsafeUtility.CopyObjectAddressToPtr
という機能があります。
もし可能であれば、利用してみるのはいかがでしょうか?
例えば、このように使います。このコードの UnsafeFieldInfo.SetValue
が FieldInfo.SetValue
よりも高速になることをご確認ください。
readonly struct UnsafeFieldInfo {
public readonly Type fieldType;
readonly int offset;
public UnsafeFieldInfo(FieldInfo fieldInfo) {
fieldType = fieldInfo.FieldType;
offset = UnsafeUtility.GetFieldOffset(fieldInfo);
}
public unsafe void SetValue(object target, object value) {
if (target == null) { return; }
var targetPtr = UnsafeUtility.PinGCObjectAndGetAddress(target, out ulong targetHandle);
UnsafeUtility.CopyObjectAddressToPtr(value, (byte*)targetPtr + offset);
UnsafeUtility.ReleaseGCObject(targetHandle);
}
}
なお、PropertyInfoにはこの方法は使えないと思われます。
Test action
Release action
VContainer/Assets/VContainer/Runtime/VContainer.asmdef.metaがignoreされているようなので、
VContainer/Assets/VContainer/Editor/VContainer.Editor.asmdefと
VContainer/Assets/VContainer/Tests/VContainer.Tests.asmdefに登録されているguidが参照できないようです。
Issue:
Solution
The issue is detected by https://openupm.com/packages/jp.hadashikick.vcontainer/?subPage=pipelines
It may be useful to be able to replace the registered items later 🤔
Perhaps we can meet the #157 requirements.
builder.TryGet<IFoo>(out var registrationBuilder);
builder.Replace(registrationBuilder, new NewFooRegistrationBuilder(..))
builder.Register<IFoo, Foo>();
builder.Register<IFoo, Bar>();
builder.Build().Resolver<IFoo>(); // which type?
Is this behavior undefined? First or Last?
Microsoft.Extensions.DependencyInjection
uses Last
registered.
This is useful for overriding arbitrarily after a plugin has registered.
LifetimeScope のインスペクターでは Auto Inject Game Objects を設定することができ、
実行時設定した GameObject 以下の MonoBehaviour (※) へ inject できるようになっています。
LifetimeScope 派生クラスでこの Auto Inject Game Objects 機能を使用してみたところ、実行時に※への injection が起こるタイミングでは既に※のAwake() や OnEnable() が実行済みであることがありました。Auto Inject Game Objects を利用した injection は、シーン中の他のコンポーネントの Awake() や OnEnable() が実行されるよりも前に起こると思い込んでいたのでこの結果は意外でした。
これは LifetimeScope 派生クラスと※の Script Execution Order が何れもデフォルト(=0)であり、どちらの Awake() が先に実行されるかが決まっていないためだと思われます。実際、LifetimeScope 派生クラスの Script Execution Order を -9999 に設定したところ、※のAwake()が実行される前に injection が起こり、意図通りの動作となりました。
なお、Zenject では Zenject.SceneContext の Script Execution Order は -9999 に設定されており、injection はシーン中の他のコンポーネントの Awake() や OnEnable() が実行されるようにも前に起こりますが、このことが私の思い込みの原因であったと思います。
Scrutor library adds a cool decorator feature for Microsoft.Extensions.DependencyInjection
. Is it possible to provide a similar thing here?
https://github.com/khellang/Scrutor
builder.Register<IPictureRepository, PictureRepository>();
builder.Decorate<IPictureRepository, CachingPictureRepository>();
builder.Decorate<IPictureRepository, LoggingPictureRepository>();
// Resolve<IPictureRepository> would resolve LoggingPictureRepository with this hierarchy of decoration
// - LoggingPictureRepository
// | - CachingPictureRepository
// | - PictureRepository
ReflectionInjector now injects Methods, Properties then Fields.
Would it be safer to reverse order? In that case Methods are injected last and can refer to other injectables. By the way Properties setters will availabled to refer to injectable Fields.
As I understand Properties/Fields injection means optional dependency, also Method injection is like constructor mean entry point of initialization. So in injected method we can figure out which optional dependencies are resolved.
I have an internal ClientInput
class implementing MonoBehaviour
in my client scene, present in the hierarchy on startup.
The way I pass down its dependencies is via the following method:
[Inject]
internal void Construct(InputCaptureSettings settings)
{ ... }
The root LifetimeScope
registers the instance present in the scene from a serialized field like so:
builder.RegisterComponent(_clientInput)
.As<IClientInput>();
Just to understand how and when the dependencies are provided, I added a Debug.Log
to the Construct
method of ClientInput
and it turns out that the method is called twice.
ClientInput
isn't listed in the "auto inject gameobject" list of any scope.
Is there something I'm not doing correctly here or is it an unexpected behavior?
Git tag: 0.2.0
package.json's version: 0.0.1
To fix: bump version, then re-tag 0.2.0.
To avoid it in the future, recommended readings:
The issue is detected by openupm build pipelines (right bottom "build issues" section). OpenUPM is an open-source UPM registry with automatic build pipelines.
以下のようにUnderTransformを使うと非アクティブなGameObjectについたComponentを登録できません。
UnderTransformを使わなければ非アクティブでも登録できるので一貫性がない動作になっています。
builder.RegisterComponentInHierarchy<TestMonoBehaviour>().UnderTransform(transform);
// Error: VContainerException: Component TestMonoBehaviour is not in the parent GameObject
原因としては以下のGetComponentInChildrenでtrueを指定していないためです。
親LifetimeScope内でUniRxを用いて値を発行すると子LifetimeScope内でその値の購読ができません。
(子LifetimeScope内で発行された値は親LifetimeScope内で購読できるので問題ないのかもしれません。)
EntryPointでUniRxのOnNext(Unit.Default)
をしてもChildEntryPointでSubscribeに値が流れてこない。
GameLifetimeScope
|
ChildLifetimeScope
public class GameLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterEntryPoint<EntryPoint>();
builder.Register<Foo>(Lifetime.Singleton).AsImplementedInterfaces();
}
}
public class EntryPoint : IStartable
{
private readonly IFoo _foo;
public EntryPoint(IFoo foo)
{
_foo = foo;
}
public void Start()
{
_foo.Publish();
}
}
public class Foo : IFoo
{
public IObservable<Unit> Observable => _subject;
private readonly Subject<Unit> _subject = new Subject<Unit>();
public void Publish()
{
_subject.OnNext(Unit.Default);
Debug.Log("FOO!");
}
}
public interface IFoo
{
IObservable<Unit> Observable { get; }
void Publish();
}
public class ChildrenLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.RegisterEntryPoint<ChildEntryPoint>();
}
}
public class ChildEntryPoint : IStartable, IDisposable
{
private readonly IFoo _foo;
private readonly CompositeDisposable _disposable = new CompositeDisposable();
public ChildEntryPoint(IFoo foo)
{
_foo = foo;
}
public void Start()
{
_foo.Observable
.Subscribe(_ => UnityEngine.Debug.Log("Observe:Foo"))
.AddTo(_disposable);
}
public void Dispose()
{
_disposable?.Dispose();
}
}
FOO!
I would like a way to more easily delegate resolving a type to another function or class. Here's my thoughts for a few new RegisterProvider
methods. The idea is that when resolving a given type T
, it would invoke the provider and inject the returned result. Unlike a Factory, a provider would be called at the time of resolution, whereas a factory is injected directly.
public static RegistrationBuilder RegisterProvider<T>(this IContainerBuilder builder, Func<T> provider) { }
public static RegistrationBuilder RegisterProvider<TParam1, T>(this IContainerBuilder builder, Func<TParam1, T> provider) { }
public static RegistrationBuilder RegisterProvider<T>(this IContainerBuilder builder, Func<IObjectResolver, T> provider) { }
public static RegistrationBuilder RegisterProvider<T>(this IContainerBuilder builder, IProvider<T> provider) { }
Here's a simple example of how it would be used
Container:
protected override void Configure(IContainerBuilder builder)
{
// Example 1: Super basic, basically equivalent to Lifetime.Transient but worse
builder.RegisterProvider(() => new Foo());
// Example 2:
builder.Register<IMyService, MyServiceImpl>();
// Delegating resolution of `Foo` to `IMyService`
builder.RegisterProvider<IMyService, Foo>(myService => myService.ProvideFoo());
// Or
builder.RegisterProvider<Foo>(resolver => resolver.Resolve<IMyService>().ProvideFoo());
}
Consumer:
public class Bar
{
// `Foo` is provided by provider specified above
public Bar(Foo myFoo)
{
myFoo.DoThing();
}
}
Maybe there is already a way of doing this sort of thing, but I haven't been able to find a good way to do it.
I faced a case where ITickable should be resolved in Transient way.
I have registration
builder.RegisterEntryPoint<ComboCounter>(Lifetime.Transient).AsSelf();
So each spawned ComboCounter is resolved but ticks are executed for other instances, which are created as ITickable for EntryPointDispatcher.
I admit the logic of this behavior. But ITickable and other entry points are treated as simple way to integrate player loop logic into C# class, however user fated to build their own player loop binding in that case.
Would it be a good decision to execute entry points only for instances that Transient resolved without entry point interfaces?
手前味噌ではございますが、 https://github.com/pCYSl5EDgo/create-unitypackage というGitHub Actionを利用しますとGableroux氏のDockerコンテナを使用する場合よりも高速にunitypackageを生成できます。
I'm trying to Inject enum Place
value. So I registered it as builder.RegisterInstance(place).As(typeof(Place))
.
But it throws at TypeAnalyzer.Analyze
if (injectConstructor == null)
{
#if UNITY_2018_4_OR_NEWER
// It seems that Unity sometimes strips the constructor of Component at build time.
// In that case, allow null.
if (!type.IsSubclassOf(typeof(UnityEngine.Component)))
#endif
throw new VContainerException(type, $"Type does not found injectable constructor, type: {type.Name}");
}
with stacktrace:
VContainer.Internal.TypeAnalyzer.Analyze (System.Type type) (at Library/PackageCache/[email protected]/Runtime/Internal/TypeAnalyzer.cs:130)
System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at <695d1cc93cca45069c528c15c9fdd749>:0)
VContainer.Internal.TypeAnalyzer.AnalyzeWithCache (System.Type type) (at Library/PackageCache/[email protected]/Runtime/Internal/TypeAnalyzer.cs:87)
VContainer.Internal.ReflectionInjector.Build (System.Type type) (at Library/PackageCache/[email protected]/Runtime/Internal/ReflectionInjector.cs:10)
VContainer.Internal.InjectorCache+<>c__DisplayClass1_0.<GetOrBuild>b__0 (System.Type type1) (at Library/PackageCache/[email protected]/Runtime/Internal/InjectorCache.cs:21)
System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) (at <695d1cc93cca45069c528c15c9fdd749>:0)
VContainer.Internal.InjectorCache.GetOrBuild (System.Type type) (at Library/PackageCache/[email protected]/Runtime/Internal/InjectorCache.cs:13)
VContainer.RegistrationBuilder.Build () (at Library/PackageCache/[email protected]/Runtime/RegistrationBuilder.cs:34)
VContainer.ContainerBuilder.BuildRegistrations () (at Library/PackageCache/[email protected]/Runtime/ContainerBuilder.cs:116)
VContainer.ScopedContainerBuilder.BuildScope () (at Library/PackageCache/[email protected]/Runtime/ContainerBuilder.cs:36)
VContainer.ScopedContainer.CreateScope (System.Action`1[T] installation) (at Library/PackageCache/[email protected]/Runtime/Container.cs:88)
Windows 10
Unity 2020.3
VContainer.1.6.0
MagicOnion.Client.Unity v4.1.2
起動時に放置していても問題ないのですが、UnityEditor上で一度Sceneを実行したあとに停止し、そのまま放置しておくと一定間隔ごとに例外が発生し続けています。
ParentReferencePropertyDrawer#GetAllTypeNames
のassembly.GetTypes
で例外が発生してしまいます。
例外が発生するとLifetimeScopeを貼っ付けてるオブジェクトのインスペクタが正しく表示されないようです。
また、MagicOnionとも関係しているようなのですが、VContainer側の処理の対応になるのかMagicOnion側か、もしくは私がなにかトチってるかが判別出来なかったため、こちらに記載させていただきました。
file:///D:/PATH/TO/Unity/Library/ScriptAssemblies/MagicOnion.Client.dll
MagicOnion.Client, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
ReflectionTypeLoadException: Exception of type 'System.Reflection.ReflectionTypeLoadException' was thrown.
System.Reflection.Assembly.GetTypes () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
VContainer.Editor.ParentReferencePropertyDrawer.GetAllTypeNames () (at Library/PackageCache/jp.hadashikick.vcontainer@e17b3fb9e9/Editor/ParentReferencePropertyDrawer.cs:18)
VContainer.Editor.ParentReferencePropertyDrawer.OnGUI (UnityEngine.Rect rect, UnityEditor.SerializedProperty prop, UnityEngine.GUIContent label) (at Library/PackageCache/jp.hadashikick.vcontainer@e17b3fb9e9/Editor/ParentReferencePropertyDrawer.cs:38)
UnityEditor.PropertyDrawer.OnGUISafe (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label) (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
UnityEditor.PropertyHandler.OnGUI (UnityEngine.Rect position, UnityEditor.SerializedProperty property, UnityEngine.GUIContent label, System.Boolean includeChildren, UnityEngine.Rect visibleArea) (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
UnityEditor.GenericInspector.OnOptimizedInspectorGUI (UnityEngine.Rect contentRect) (at <50f55621a2ca4f31a35283e2979a8bf5>:0)
UnityEditor.UIElements.InspectorElement+<>c__DisplayClass59_0.<CreateIMGUIInspectorFromEditor>b__0 () (at <1d96ce257f0e45ff836d157d33fd933d>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)
試したこと
Repro steps:
VContainer
from OpenUPMPackage Development
from Unity RegistryGUID [1eb7e6f92b1d7d64ba0a48ea751728f3] for asset 'Packages/nuget.mono-cecil/CHANGELOG.md' conflicts with:
'Packages/com.unity.nuget.mono-cecil/CHANGELOG.md' (current owner)
We can't assign a new GUID because the asset is in an immutable folder. The asset will be ignored.
Hey, VContainer looks great but looking at the docs it seems it doesn’t currently support spawning of objects at runtime via Factories, is that the case? Same question for unconstructed generic types: for example is there a way to bind all types that implement interface IEventHandler from specified Assembly?
when using:
using (LifetimeScope.EnqueueParent(parent))
{
await SceneManager.LoadSceneAsync("...", LoadSceneMode.Additive);
}
things are resolved correctly in child container from parent container but in case of:
using (LifetimeScope.EnqueueParent(parent))
{
SceneManager.LoadScene("...", LoadSceneMode.Additive);
}
parent container is not configured properly
I think the argument is also a concrete type because it registers a concrete type.
diff --git a/README.md b/README.md
index 955667e..5231ebe 100644
--- a/README.md
+++ b/README.md
@@ -436,7 +436,7 @@ It can resolve like this:
```csharp
class ClassA
{
- public ClassA(IServiceA serviceA) { /* ... */ }
+ public ClassA(ServiceA serviceA) { /* ... */ }
}
```
Hey there,
I was thinking of trying this out and as I was reading the instructions I saw it had playerloop integration, which made me think it would be a good idea to ask if you happen to know if this is compatible with DOTS/ECS?
Thanks,
-MH
I would like to write the process after IContainerBuilder is built as follows.
public class CustomLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
}
// I want this virtual method!!!
protected override void OnAfterBuild(IObjectResolver resolver)
{
resolver.Inject(obj);
}
}
I can do the same with builder.RegisterBuildCallback
, but it is hard to understand at first glance.
I think it will be easier to understand if we can standardize how to write as shown above.
Sometimes you might have multiple instances that could collide and it would be useful to be able to distinguish between them when resolving.
For instance:
builder.Register<Logger>(name: "StdOut", Lifetime.Singleton);
builder.Register<Logger>(name: "StdErr", Lifetime.Singleton);
A consumer could then specify which named logger they want injected:
class Foo
{
Foo([InjectNamed("StdOut")] Logger logger) { }
}
// or both!
class Bar
{
Bar([InjectNamed("StdOut")] Logger stdLogger, [InjectNamed("StdErr")] Logger errLogger) { }
}
Can also be used to resolve primitives which could then be resolved throughout the container without needing to specify a WithParameter
for every case where it is used:
builder.RegisterInstance<string>("https://www.my-url.com", name: "MyUrl");
Has this library (or will it have) an alternative to Zenject's IMemoryPool?
It's a question not a feature request. If it's not in this library it's fine because there are plenty libraries for this. I'd love to see this in some kind of "we do not support" section in the docs :)
version: 1.7.0
unity: 2020.3.1f1
using UnityEngine;
using VContainer;
public interface IFoo {}
public class Foo : IFoo {}
public interface IBar {}
public class Bar : IBar
{
public Bar(IFoo _) {}
}
public class TestScope : MonoBehaviour
{
void Awake()
{
var builder = new ContainerBuilder();
var container = builder.Build();
container.CreateScope(b =>
{
b.Register<Foo>(Lifetime.Singleton).AsImplementedInterfaces();
b.Register<Bar>(Lifetime.Singleton).AsImplementedInterfaces();
b.RegisterBuildCallback(c => c.Resolve<IBar>()); // error: VContainerException: Failed to resolve Bar : No such registration of type: IFoo
});
}
}
VContainerException: Failed to resolve Bar : No such registration of type: IFoo
VContainer.Internal.ReflectionInjector.CreateInstance (VContainer.IObjectResolver resolver, System.Collections.Generic.IReadOnlyList`1[T] parameters) (at Library/PackageCache/[email protected]/Runtime/Internal/ReflectionInjector.cs:46)
VContainer.Internal.Registration.SpawnInstance (VContainer.IObjectResolver resolver) (at Library/PackageCache/[email protected]/Runtime/Internal/Registration.cs:44)
VContainer.Container+<>c__DisplayClass5_0.<.ctor>b__1 () (at Library/PackageCache/[email protected]/Runtime/Container.cs:152)
System.Lazy`1[T].CreateValue () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Lazy`1[T].LazyInitValue () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
System.Lazy`1[T].get_Value () (at <eae584ce26bc40229c1b1aa476bfa589>:0)
VContainer.Container.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/[email protected]/Runtime/Container.cs:174)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/[email protected]/Runtime/Container.cs:69)
VContainer.ScopedContainer.Resolve (VContainer.IRegistration registration) (at Library/PackageCache/[email protected]/Runtime/Container.cs:72)
VContainer.ScopedContainer.Resolve (System.Type type) (at Library/PackageCache/[email protected]/Runtime/Container.cs:57)
VContainer.IObjectResolverExtensions.Resolve[T] (VContainer.IObjectResolver resolver) (at Library/PackageCache/[email protected]/Runtime/IObjectResolverExtensions.cs:8)
TestScope+<>c.<Awake>b__0_1 (VContainer.IObjectResolver c) (at Assets/TestScope.cs:23)
VContainer.ContainerBuilder.EmitCallbacks (VContainer.IObjectResolver container, System.Collections.Generic.IEnumerable`1[T] callbacks) (at Library/PackageCache/[email protected]/Runtime/ContainerBuilder.cs:158)
VContainer.ScopedContainerBuilder.BuildScope () (at Library/PackageCache/[email protected]/Runtime/ContainerBuilder.cs:39)
VContainer.ScopedContainer.CreateScope (System.Action`1[T] installation) (at Library/PackageCache/[email protected]/Runtime/Container.cs:88)
VContainer.Container.CreateScope (System.Action`1[T] installation) (at Library/PackageCache/[email protected]/Runtime/Container.cs:189)
TestScope.Awake () (at Assets/TestScope.cs:19)
Hello! Upgraded to latest official (non-beta) unity release and have following error on startup:
ArgumentException: UnityEngine.PlayerLoop.EarlyUpdate+ScriptRunDelayedStartupFrame not in system Initialization UnityEngine.PlayerLoop.Initialization
VContainer.Unity.PlayerLoopHelper.InsertSubsystem (UnityEngine.LowLevel.PlayerLoopSystem& parentSystem, System.Type before, UnityEngine.LowLevel.PlayerLoopSystem newSystem, UnityEngine.LowLevel.PlayerLoopSystem newPostSystem) (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/PlayerLoopHelper.cs:180)
VContainer.Unity.PlayerLoopHelper.Initialize () (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/PlayerLoopHelper.cs:72)
VContainer.Unity.LifetimeScope.ActivateEntryPoints () (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/LifetimeScope.cs:290)
VContainer.Unity.LifetimeScope.Build () (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/LifetimeScope.cs:175)
VContainer.Unity.LifetimeScope.GetRuntimeParent () (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/LifetimeScope.cs:266)
VContainer.Unity.LifetimeScope.Awake () (at Library/PackageCache/jp.hadashikick.vcontainer@16f243a128/Runtime/Unity/LifetimeScope.cs:131)
下記の手順でMagicOnionがクラッシュします。
LifetimeScopeがSceneにない状態でMagicOnionの実行が出来る、複数回の起動でクラッシュしていないことは確認済みです。
(今回のサンプルだと実行は確認出来ません)
using VContainer;
using VContainer.Unity;
public class GameLifetimeScope : LifetimeScope
{
protected override void Configure(IContainerBuilder builder)
{
builder.Register<HelloWorldService>(Lifetime.Singleton);
builder.RegisterEntryPoint<GamePresenter>(Lifetime.Singleton);
}
}
public class HelloWorldService
{
// 読み込ませるだけなので処理なし
}
using VContainer.Unity;
public class GamePresenter : IStartable
{
private readonly HelloWorldService _helloWorldService;
public GamePresenter(HelloWorldService helloWorldService)
{
_helloWorldService = helloWorldService;
}
void IStartable.Start()
{
// 特に何もしない
}
}
GamePresenter.csからIStartableの実装を抜いた状態にするとクラッシュしなくなりました。
ただし、一度クラッシュするようになっているとUnity再起動するまで関係なくクラッシュし続けるようです。
- public class GamePresenter : IStartable
+ public class GamePresenter
{
private readonly HelloWorldService _helloWorldService;
public GamePresenter(HelloWorldService helloWorldService)
{
_helloWorldService = helloWorldService;
}
- void IStartable.Start()
- {
- // 特に何もしない
- }
}
Error: Could not load signature of MagicOnion.ChannelExtensions:RegisterStreamingSubscription due to: Could not load file or assembly 'Grpc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad' or one of its dependencies. assembly:Grpc.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad type:<unknown type> member:(null) signature:<none>
Error: Could not load signature of MagicOnion.MetadataExtensions:Get due to: Could not load file or assembly 'Grpc.Core.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad' or one of its dependencies. assembly:Grpc.Core.Api, Version=2.0.0.0, Culture=neutral, PublicKeyToken=d754f35622e28bad type:<unknown type> member:(null) signature:<none>
Unloading broken assembly Library/ScriptAssemblies/MagicOnion.Unity.dll, this assembly can cause crashes in the runtime
Unloading broken assembly Library/ScriptAssemblies/MagicOnion.Client.dll, this assembly can cause crashes in the runtime
In the 1.8.1 version there is no "None" option to select in Parent section of a LifetimeScope. It is there in 1.8.0
IContainerBuilder
provides public Register(RegistrationBuilder)
method which is completely useless given that all the constructors of RegistrationBuilder
are internal
. Taking this into account, there are two options:
internal IContainerBuilder.Register(RegistrationBuilder)
RegistrationBuilder
more open for extensionIMO (2) is a better option since I've already got into a situation where a custom RegistrationBuilder
would be useful.
Hello! I am trying to create separate installer for ScriptableObject
for RootLifetimeScope
in VContainerSettings
.
The way I am doing it is this:
public class ScriptableObjectsInstaller : ScriptableObject, IInstaller
{
[SerializeField]
private EncryptionSettings _encryptionSettings;
public void Install(IContainerBuilder builder)
{
builder.RegisterInstance<AuthenticationStorage>(new AuthenticationStorage(_encryptionSettings));
}
}
And then in RootLifetimeScope
:
public class RootLifetimeScope : LifetimeScope
{
[SerializeField]
private ScriptableObjectsInstaller _scriptableObjectsInstallers;
protected override void Configure(IContainerBuilder builder)
{
Push(_scriptableObjectsInstallers);
}
}
The problem is that the method Install
in ScriptableObjectsInstaller
seems to be called several times, once for each LifetimeScope
in scene. E.g. if I have 3 scenes additevely loaded, then it will be called 3 times.
Is it intended behaviour or bug?
If it's intented, then how to accomplish the behaviour I want? To be clear:
I don't want to bloat RootLifetimeScope
with tons of references to different ScriptableObject
, so I want to group them in separate installers and just "feed" them to RootLifetimeScope
.
when using IObjectResolver
directly, can not resolver IObjectResolver
itself.
var builder = new ContainerBuilder();
var resolver = builder.Build();
var resolver2 = r.Resolve<IObjectResolver>(); // exception, not registered
I'm currently using the following code for unit testing.
public class VContainerTest
{
[Test]
public void VContainerTestSimplePasses()
{
var builder = new ContainerBuilder();
builder.Register<MyClass>(Lifetime.Transient);
var resolver = builder.Build();
// exception, can not resolve IObjectResolver...
var mc = resolver.Resolve<MyClass>();
}
}
public class MyClass
{
readonly IObjectResolver resolver;
public MyClass(IObjectResolver resolver)
{
this.resolver = resolver;
}
}
Do you have any workaround?
In 2020.2 and later, the behavior of ILPostProcessor seems to have changed.
MissingMethodException
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.