示例#1
0
        //TODO: Implement full caching to remember injectable fields for certain types.
        public void Inject()
        {
            try
            {
                //TODO: Check if autofac performance better than this.
                //TODO: Implement FreecraftCore injection lambdas
                foreach (MemberInfo mi in ObjectType.FieldsAndPropertiesWith(Flags.InstanceAnyVisibility, typeof(InjectAttribute)))
                {
                    //Skip if the field/prop is marked with OnlyIfNull but is not null.
                    if (mi.Attribute <InjectOnlyIfNullAttribute>() != null)
                    {
                        if (mi.Get(ObjectInstance) != null)
                        {
                            continue;
                        }
                    }

                    //Based on FreecraftCore's: https://github.com/FreecraftCore/FreecraftCore.Serializer/blob/152fda27c46fcfcaa72d3568c1a591d728773f33/src/FreecraftCore.Serializer.API/Reflection/Serialization/MemberSerializationMediator.cs
                    if (mi is PropertyInfo && !((PropertyInfo)mi).CanWrite)
                    {
                        //TODO: Unity2018 has issues with this FasterFlect PlatformNotSupportedException: Operation is not supported on this platform.
                        //If it's a property and it's a readonly one we'll try to grab the backing field
                        //ObjectInstance.SetFieldValue($"<{mi.Name}>k__BackingField", Resolver.Resolve(mi.Type()));
                        FieldInfo field = ObjectType.GetField($"<{mi.Name}>k__BackingField", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);
                        if (field == null)
                        {
                            throw new InvalidOperationException($"Unable to get backing field for {mi.Name}");
                        }

                        field.SetValue(ObjectInstance, Resolver.Resolve(mi.Type()), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField, null, CultureInfo.CurrentCulture);
                        //ObjectInstance.SetFieldValue($"<{mi.Name}>k__BackingField", Resolver.Resolve(mi.Type()));
                    }
                    else
                    {
                        //TODO: Unity2018 has issues with this FasterFlect PlatformNotSupportedException: Operation is not supported on this platform.
                        //mi.Set(ObjectInstance, Resolver.Resolve(mi.Type()));
                        if (mi is PropertyInfo p)
                        {
                            p.SetValue(ObjectInstance, Resolver.Resolve(mi.Type()));
                        }
                        else if (mi is FieldInfo f)
                        {
                            f.SetValue(ObjectInstance, Resolver.Resolve(mi.Type()));
                        }
                    }
                }

                //If we didn't fail we should invoke the dependency injection callbacks
                //if the object implemented them
                if (this.ObjectInstance is IDependencyInjectionCallbackable dpc)
                {
                    dpc.OnDependencyInjectionFinished();
                }
            }
            catch (Exception e)
            {
                throw new InvalidOperationException($"Error: {e.Message} failed to inject for {ObjectType} on instance: {ObjectInstance}", e);
            }
        }