Кажется, что с operator.add
возникает путаница! Когда вы добавляете два списка вместе, правильным термином для этого является concat
, а не добавлять. operator.concat
- это то, что вам нужно использовать.
Если вы думаете о функциональности, это так же просто, как это ::
>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)
. Вы видите, что уменьшают уважение к типу последовательности, поэтому, когда вы поставляете кортеж, вы возвращаете кортеж. давайте попробуем со списком ::
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Aha, вы получите список.
Как насчет производительности ::
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop
from_iterable довольно быстро! Но это не сравнимо с уменьшением с concat.
>>> list2d = ((1,2,3),(4,5,6), (7,), (8,9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
Согласно вашему комментарию, вам нужно использовать ServiceLocator для получения экземпляра вашего ConfigurationRepository, потому что экземпляр конвертера не создан Unity, а движком Silverlight / XAML.
Таким образом, ваша собственность, украшенная атрибутом DependencyAttribute, не будет введена.
c #
public class SomeValueToBrushConverter : IValueConverter
{
public SomeValueToBrushConverter(){
ConfigurationRepository = ServiceLocator.Current.GetInstance<ConfigurationRepository>();
}
private ConfigurationRepository ConfigurationRepository { get; set; }
}
В вашем методе RegisterTypes вам необходимо настроить ServiceLocator:
_container = new UnityContainer();
UnityServiceLocator locator = new UnityServiceLocator(_container);
ServiceLocator.SetLocatorProvider(() => locator);
Можно использовать MarkupExtension
для разрешения зависимостей из контейнера DI:
public class IocResolver : MarkupExtension
{
public IocResolver()
{ }
public IocResolver(string namedInstance)
{
NamedInstance = namedInstance;
}
[ConstructorArgument("namedInstance")]
public string NamedInstance { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
var provideValueTarget = (IProvideValueTarget)serviceProvider
.GetService(typeof(IProvideValueTarget));
// Find the type of the property we are resolving
var targetProperty = provideValueTarget.TargetProperty as PropertyInfo;
if (targetProperty == null)
throw new InvalidProgramException();
Debug.Assert(Resolve != null, "Resolve must not be null. Please initialize resolving method during application startup.");
Debug.Assert(ResolveNamed != null, "Resolve must not be null. Please initialize resolving method during application startup.");
// Find the implementation of the type in the container
return NamedInstance == null
? (Resolve != null ? Resolve(targetProperty.PropertyType) : DependencyProperty.UnsetValue)
: (ResolveNamed != null ? ResolveNamed(targetProperty.PropertyType, NamedInstance) : DependencyProperty.UnsetValue);
}
public static Func<Type, object> Resolve { get; set; }
public static Func<Type, string, object> ResolveNamed { get; set; }
}
IocResolver необходимо инициализировать во время запуска приложения, например:
IocResolver.Resolve = kernel.Get;
IocResolver.ResolveNamed = kernel.GetNamed;
// or what ever your DI container looks like
После этого вы можете использовать его в XAML для инъекции зависимости в XAML:
<!-- Resolve an instance based on the type of property 'SomeValueToBrushConverter' -->
<MyConverter SomeValueToBrushConverter="{services:IocResolver}" />
<!-- Resolve a named instance based on the type of property 'SomeValueToBrushConverter' and the name 'MyName' -->
<MyConverter SomeValueToBrushConverter="{services:IocResolver NamedInstance=MyName}" />