Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

- added enum and custom methods for filtering properties

  • Loading branch information...
commit be3f200b452ba8c0d69fa443bece09c558f5f6de 1 parent c6847d1
@kkozmic kkozmic authored
View
1  src/Castle.Windsor/Castle.Windsor.csproj
@@ -346,6 +346,7 @@
<Compile Include="Core\PerWebRequestAttribute.cs" />
<Compile Include="Core\PooledAttribute.cs" />
<Compile Include="Core\PropertiesInspectionBehavior.cs" />
+ <Compile Include="Core\DynamicPropertyFilter.cs" />
<Compile Include="Core\PropertyFilter.cs" />
<Compile Include="Core\ScopedAttribute.cs" />
<Compile Include="Core\SingletonAttribute.cs" />
View
92 src/Castle.Windsor/Core/DynamicPropertyFilter.cs
@@ -0,0 +1,92 @@
+// Copyright 2004-2011 Castle Project - http://www.castleproject.org/
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+namespace Castle.Core
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Reflection;
+
+ using Castle.Core.Internal;
+
+ public class DynamicPropertyFilter
+ {
+ private readonly Func<ComponentModel, PropertyInfo, bool> filter;
+
+ public DynamicPropertyFilter(Func<ComponentModel, PropertyInfo, bool> filter, bool isRequired)
+ {
+ this.filter = filter;
+ IsRequired = isRequired;
+ }
+
+ public bool IsRequired { get; private set; }
+
+ public bool Matches(ComponentModel component, PropertyInfo property)
+ {
+ return filter(component, property);
+ }
+
+ public static DynamicPropertyFilter Create(PropertyFilter filter)
+ {
+ switch (filter)
+ {
+ case PropertyFilter.Default:
+ return Default();
+ case PropertyFilter.IgnoreBase:
+ return IgnoreBase();
+ case PropertyFilter.RequireAll:
+ return RequireAll();
+ case PropertyFilter.RequireBase:
+ return RequireBase();
+ default:
+ throw new ArgumentOutOfRangeException(
+ string.Format(
+ "The value {0} does not translate to a valid property filter. This is most likely a bug in the calling code.",
+ filter));
+ }
+ }
+
+ public static DynamicPropertyFilter Default()
+ {
+ return new DynamicPropertyFilter(delegate { return true; }, false);
+ }
+
+ public static ICollection<DynamicPropertyFilter> GetPropertyFilters(ComponentModel componentModel,
+ bool createIfMissing)
+ {
+ var filters = (ICollection<DynamicPropertyFilter>)componentModel.ExtendedProperties[Constants.PropertyFilters];
+ if (filters == null && createIfMissing)
+ {
+ filters = new List<DynamicPropertyFilter>(4);
+ componentModel.ExtendedProperties[Constants.PropertyFilters] = filters;
+ }
+ return filters;
+ }
+
+ private static DynamicPropertyFilter IgnoreBase()
+ {
+ return new DynamicPropertyFilter((m, p) => m.Implementation == p.DeclaringType, false);
+ }
+
+ private static DynamicPropertyFilter RequireAll()
+ {
+ return new DynamicPropertyFilter(delegate { return true; }, true);
+ }
+
+ private static DynamicPropertyFilter RequireBase()
+ {
+ return new DynamicPropertyFilter((m, p) => m.Implementation != p.DeclaringType, true);
+ }
+ }
+}
View
52 src/Castle.Windsor/Core/PropertyFilter.cs
@@ -14,38 +14,32 @@
namespace Castle.Core
{
- using System;
- using System.Collections.Generic;
- using System.Reflection;
-
- using Castle.Core.Internal;
-
- public class PropertyFilter
+ /// <summary>
+ /// Specifies rules for designating settable properties on a component as dependencies, and controlling whether they are requred or not. This is a shortcut for most common scenarios. More advanced/custom scenarios can be defined dynamically in the registration API.
+ /// </summary>
+ public enum PropertyFilter
{
- private readonly Predicate<PropertyInfo> filter;
-
- public PropertyFilter(Predicate<PropertyInfo> filter, bool isRequired)
- {
- this.filter = filter;
- IsRequired = isRequired;
- }
+ /// <summary>
+ /// Takes no action. By default that means all settable properties will be exposed as optional dependencies.
+ /// </summary>
+ Default,
- public bool IsRequired { get; private set; }
+ /// <summary>
+ /// Makes all property dependencies required.
+ /// </summary>
+ RequireAll,
- public bool Matches(PropertyInfo property)
- {
- return filter(property);
- }
+ /// <summary>
+ /// Makes all property dependencies defined at a base class/interfaces level required.
+ /// </summary>
+ RequireBase,
- public static ICollection<PropertyFilter> GetPropertyFilters(ComponentModel componentModel, bool createIfMissing)
- {
- var filters = (ICollection<PropertyFilter>)componentModel.ExtendedProperties[Constants.PropertyFilters];
- if (filters == null && createIfMissing)
- {
- filters = new List<PropertyFilter>(4);
- componentModel.ExtendedProperties[Constants.PropertyFilters] = filters;
- }
- return filters;
- }
+ /// <summary>
+ /// Ignores all properties defined at a base class/interface level.
+ /// </summary>
+ /// <remarks>
+ /// This option is particularily useful in scenarios like UI controls which in .NET UI frameworks tend to have byzantine inheritance hierarchies.
+ /// </remarks>
+ IgnoreBase
}
}
View
7 src/Castle.Windsor/MicroKernel/ModelBuilder/Inspectors/PropertiesDependenciesModelInspector.cs
@@ -69,7 +69,7 @@ protected virtual void InspectProperties(ComponentModel model)
}
var properties = GetProperties(model, targetType);
- var filters = PropertyFilter.GetPropertyFilters(model, false);
+ var filters = DynamicPropertyFilter.GetPropertyFilters(model, false);
foreach (var property in properties)
{
if (IsSettable(property) == false)
@@ -151,11 +151,12 @@ private PropertyInfo[] GetProperties(ComponentModel model, Type targetType)
return properties;
}
- private static void ApplyFilters(ComponentModel model, PropertyInfo property, IEnumerable<PropertyFilter> filters)
+ private static void ApplyFilters(ComponentModel model, PropertyInfo property,
+ IEnumerable<DynamicPropertyFilter> filters)
{
foreach (var filter in filters)
{
- if (filter.Matches(property))
+ if (filter.Matches(model, property))
{
var dependency = new DependencyModel(property.Name, property.PropertyType, isOptional: filter.IsRequired == false);
model.AddProperty(new PropertySet(property, dependency));
View
51 src/Castle.Windsor/MicroKernel/Registration/ComponentRegistration.cs
@@ -1106,12 +1106,59 @@ public ComponentRegistration<TService> IsDefault()
/// </summary>
/// <param name = "filter">Predicate deciding whether a property is settable or not. If returns <c>false</c> container will ignore the property, otherwise property will be ignored.</param>
/// <returns></returns>
+ /// <remarks>
+ /// Matched properties will be considered optional, that is component will resolve successfully if they can not be satisfied.
+ /// </remarks>
public ComponentRegistration<TService> Properties(Predicate<PropertyInfo> filter)
{
+ return Properties(filter, isRequired: false);
+ }
+
+ /// <summary>
+ /// Filters properties on the implementation that will be considered 'settable' by the container and specifies if matched properties are reqired.
+ /// </summary>
+ /// <param name = "filter">Predicate deciding whether a property is settable or not. If returns <c>false</c> container will ignore the property.</param>
+ /// <param name = "isRequired"></param>
+ /// <returns></returns>
+ /// <remarks>
+ /// Matched properties will be considered optional if <paramref name = "isRequired" /> is<c>false</c>, that is component will resolve successfully if they can not be satisfied.
+ /// If the argument is <c>true</c> and the dependencies can not be resolved the component will fail to resolve.
+ /// </remarks>
+ public ComponentRegistration<TService> Properties(Predicate<PropertyInfo> filter, bool isRequired)
+ {
+ return Properties((_, p) => filter(p), isRequired);
+ }
+
+ /// <summary>
+ /// Filters properties on the implementation that will be considered 'settable' by the container and specifies if matched properties are reqired.
+ /// </summary>
+ /// <param name = "filter">Predicate deciding whether a property is settable or not. If returns <c>false</c> container will ignore the property.</param>
+ /// <param name = "isRequired"></param>
+ /// <returns></returns>
+ /// <remarks>
+ /// Matched properties will be considered optional if <paramref name = "isRequired" /> is<c>false</c>, that is component will resolve successfully if they can not be satisfied.
+ /// If the argument is <c>true</c> and the dependencies can not be resolved the component will fail to resolve.
+ /// </remarks>
+ public ComponentRegistration<TService> Properties(Func<ComponentModel, PropertyInfo, bool> filter, bool isRequired)
+ {
+ return AddDescriptor(new DelegatingModelDescriptor(builder: (k, c) =>
+ {
+ var filters = DynamicPropertyFilter.GetPropertyFilters(c, createIfMissing: true);
+ filters.Add(new DynamicPropertyFilter(filter, isRequired: isRequired));
+ }));
+ }
+
+ /// <summary>
+ /// Filters properties on the implementation that will be considered 'settable' by the container and specifies if matched properties are reqired.
+ /// </summary>
+ /// <param name = "filter">Rules for deciding whether a property is settable or not and if container will ignore the property.</param>
+ /// <returns></returns>
+ public ComponentRegistration<TService> Properties(PropertyFilter filter)
+ {
return AddDescriptor(new DelegatingModelDescriptor(builder: (k, c) =>
{
- var filters = PropertyFilter.GetPropertyFilters(c, createIfMissing: true);
- filters.Add(new PropertyFilter(filter, isRequired: false));
+ var filters = DynamicPropertyFilter.GetPropertyFilters(c, createIfMissing: true);
+ filters.Add(DynamicPropertyFilter.Create(filter));
}));
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.