Skip to content

Commit 48da45d

Browse files
committed
A viable proof of concept for providing CW-injected objects to COM consumers. RPS is used as a model, but subsequent PR will further encapsulate in order to only expose parser events to enable cache invalidation for type cache which must be outside the CW graph.
1 parent 975e4d8 commit 48da45d

File tree

5 files changed

+108
-21
lines changed

5 files changed

+108
-21
lines changed

Rubberduck.Main/Extension.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ private void Startup()
230230
currentDomain.AssemblyResolve += LoadFromSameFolder;
231231

232232
_container = new WindsorContainer().Install(new RubberduckIoCInstaller(_vbe, _addin, _initialSettings, _vbeNativeApi, _beepInterceptor));
233-
233+
_container.Resolve<InstanceProvider>();
234234
_app = _container.Resolve<App>();
235235
_app.Startup();
236236

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using Rubberduck.Parsing.VBA;
3+
4+
namespace Rubberduck.Root
5+
{
6+
public interface IInstanceProvider
7+
{
8+
RubberduckParserState StateInstance { get; }
9+
}
10+
11+
public static class InstanceProviderFactory
12+
{
13+
public static IInstanceProvider GetInstanceProvider => new InstanceProvider();
14+
}
15+
16+
internal class InstanceProvider : IInstanceProvider
17+
{
18+
private static RubberduckParserState _stateInstance;
19+
public static RubberduckParserState StateInstance
20+
{
21+
get => _stateInstance;
22+
set => _stateInstance = value ?? throw new NullReferenceException();
23+
}
24+
25+
RubberduckParserState IInstanceProvider.StateInstance => _stateInstance;
26+
}
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using Castle.Core;
6+
using Castle.MicroKernel;
7+
using Castle.MicroKernel.ModelBuilder;
8+
9+
namespace Rubberduck.Root
10+
{
11+
internal class RubberduckInstanceProviderPropertiesInspector : IContributeComponentModelConstruction
12+
{
13+
public void ProcessModel(IKernel kernel, ComponentModel model)
14+
{
15+
var targetType = model.Implementation;
16+
17+
if (!(targetType == typeof(InstanceProvider)))
18+
{
19+
return;
20+
}
21+
22+
var properties = GetProperties(model, targetType);
23+
24+
foreach (var property in properties)
25+
{
26+
model.AddProperty(BuildDependency(property));
27+
}
28+
}
29+
30+
private PropertySet BuildDependency(PropertyInfo property)
31+
{
32+
var dependency = new PropertyDependencyModel(property, isOptional: false);
33+
return new PropertySet(property, dependency);
34+
}
35+
36+
private IEnumerable<PropertyInfo> GetProperties(ComponentModel model, Type targetType)
37+
{
38+
const BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly;
39+
return targetType.GetProperties(bindingFlags).ToList()
40+
.Where(property => property.CanWrite
41+
&& property.GetSetMethod(true) != null
42+
&& !property.PropertyType.IsAbstract
43+
&& property.Name.EndsWith("Instance"));
44+
}
45+
}
46+
}

Rubberduck.Main/Root/RubberduckIoCInstaller.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ public void Install(IWindsorContainer container, IConfigurationStore store)
189189
RegisterSpecialFactories(container);
190190
RegisterFactories(container, assembliesToRegister);
191191

192+
RegisterInstanceProvider(container);
193+
192194
ApplyDefaultInterfaceConvention(container, assembliesToRegister);
193195
}
194196

@@ -288,7 +290,8 @@ private void ApplyDefaultInterfaceConvention(IWindsorContainer container, Assemb
288290
&& !type.Name.EndsWith("ConfigProvider")
289291
&& !type.Name.EndsWith("FakesProvider")
290292
&& !type.GetInterfaces().Contains(typeof(IInspection))
291-
&& type.NotDisabledOrExperimental(_initialSettings))
293+
&& type.NotDisabledOrExperimental(_initialSettings)
294+
&& type != typeof(InstanceProvider))
292295
.WithService.DefaultInterfaces()
293296
.LifestyleTransient()
294297
);
@@ -311,6 +314,20 @@ private void RegisterFactories(IWindsorContainer container, Assembly[] assemblie
311314
}
312315
}
313316

317+
private void RegisterInstanceProvider(IWindsorContainer container)
318+
{
319+
/*
320+
container.Register(Types.FromAssemblyContaining<InstanceProvider>()
321+
.IncludeNonPublicTypes()
322+
.Where(type => type == typeof(InstanceProvider))
323+
.WithServiceSelf()
324+
.LifestyleTransient()
325+
);*/
326+
container.Register(
327+
Component.For<InstanceProvider>()
328+
.LifestyleSingleton());
329+
}
330+
314331
private void RegisterSourceCodeHandlers(IWindsorContainer container)
315332
{
316333
container.Register(Component.For<ISourceCodeHandler>()
@@ -846,7 +863,8 @@ private void OverridePropertyInjection(IWindsorContainer container)
846863
.Single();
847864
container.Kernel.ComponentModelBuilder.RemoveContributor(propInjector);
848865

849-
container.Kernel.ComponentModelBuilder.AddContributor(new RubberduckPropertiesInspector());
866+
container.Kernel.ComponentModelBuilder.AddContributor(new RubberduckViewModelPropertiesInspector());
867+
container.Kernel.ComponentModelBuilder.AddContributor(new RubberduckInstanceProviderPropertiesInspector());
850868
}
851869

852870
private void RegisterParsingEngine(IWindsorContainer container)

Rubberduck.Main/Root/RubberduckPropertiesInspector.cs renamed to Rubberduck.Main/Root/RubberduckViewModelPropertiesInspector.cs

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
1-
using Castle.Core;
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Reflection;
5+
using Castle.Core;
26
using Castle.MicroKernel;
37
using Castle.MicroKernel.ModelBuilder;
4-
using Castle.MicroKernel.ModelBuilder.Inspectors;
5-
using Castle.MicroKernel.SubSystems.Conversion;
68
using Rubberduck.UI;
79
using Rubberduck.UI.Command;
8-
using System;
9-
using System.Collections.Generic;
10-
using System.Linq;
11-
using System.Reflection;
12-
using System.Text;
13-
using System.Threading.Tasks;
1410

1511
namespace Rubberduck.Root
1612
{
1713
// Loosely based on https://github.com/castleproject/Windsor/blob/36fbebd9a471f88b43044f39704dc5f19e669e6f/src/Castle.Windsor/MicroKernel/ModelBuilder/Inspectors/PropertiesDependenciesModelInspector.cs
18-
class RubberduckPropertiesInspector : IContributeComponentModelConstruction
14+
internal class RubberduckViewModelPropertiesInspector : IContributeComponentModelConstruction
1915
{
2016
public void ProcessModel(IKernel kernel, ComponentModel model)
2117
{
@@ -27,11 +23,7 @@ public void ProcessModel(IKernel kernel, ComponentModel model)
2723
return;
2824
}
2925

30-
var properties = GetProperties(model, targetType)
31-
.Where(property => property.CanWrite
32-
&& property.GetSetMethod() != null
33-
&& property.PropertyType.IsBasedOn(typeof(CommandBase))
34-
&& !property.PropertyType.IsAbstract);
26+
var properties = GetProperties(model, targetType);
3527

3628
foreach (var property in properties)
3729
{
@@ -45,10 +37,14 @@ private PropertySet BuildDependency(PropertyInfo property)
4537
return new PropertySet(property, dependency);
4638
}
4739

48-
private List<PropertyInfo> GetProperties(ComponentModel model, Type targetType)
40+
private IEnumerable<PropertyInfo> GetProperties(ComponentModel model, Type targetType)
4941
{
50-
var bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
51-
return targetType.GetProperties(bindingFlags).ToList();
42+
const BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly;
43+
return targetType.GetProperties(bindingFlags).ToList()
44+
.Where(property => property.CanWrite
45+
&& property.GetSetMethod() != null
46+
&& property.PropertyType.IsBasedOn(typeof(CommandBase))
47+
&& !property.PropertyType.IsAbstract);
5248
}
5349
}
5450
}

0 commit comments

Comments
 (0)