Первые шаги с Unity Application Block - Part 2

понедельник, 22 марта 2010, Bobasoft

В продолжении темы расмотрим как использовать generic типы в Unity.

Создадим вот такой интерфейс и класс к нему:

public interface IMessenger<T> : IMessenger
{
}
public class Messenger<T> : IMessenger
{
	public string Message
	{
		get { return String.Format("Messenger<{0}>", typeof(T).Name); }
	}
}

также модифицируем конфигурационный файл:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" requirePermission="false"/>
	</configSections>
	<unity>
		<typeAliases>
			<typeAlias alias="IMessenger" type="UnityAppBlock.IMessenger, UnityAppBlock"/>
			<typeAlias alias="Messenger" type="UnityAppBlock.Messenger, UnityAppBlock"/>
            
			<typeAlias alias="IMessengerT" type="UnityAppBlock.IMessenger`1, UnityAppBlock"/>
			<typeAlias alias="MessengerT" type="UnityAppBlock.Messenger`1, UnityAppBlock"/>
		</typeAliases>
		<containers>
			<container>
				<types>
					<type type="IMessenger" mapTo="Messenger"/>
                    
					<type type="IMessengerT" mapTo="MessengerT"/>
				</types>
			</container>
		</containers>
	</unity>
</configuration>

как видим, чтобы сказать что типа является generic нужно поставить знак ` после которого идет количество типов.

И добавим код в ф-цию Main:

static void Main(string[] args)
{
    IUnityContainer container = new UnityContainer();

    var section =
       (UnityConfigurationSection)ConfigurationManager.GetSection("unity");

    section.Containers.Default.Configure(container);

    IMessenger messenger = container.Resolve<IMessenger>();
    Console.WriteLine(messenger.Message);

    Console.WriteLine("\n-- Generic --");

    messenger = container.Resolve<IMessenger<int>>() as IMessenger;
    Console.WriteLine(messenger.Message);

    messenger = container.Resolve<IMessenger<double>>() as IMessenger;
    Console.WriteLine(messenger.Message);
    
    messenger = container.Resolve<IMessenger<string>>() as IMessenger;
    Console.WriteLine(messenger.Message);

    Console.ReadLine();
}

На экране увидим следующие:

Just messenger

-- Generic --
Messenger<Int32>
Messenger<Double>
Messenger<String>

--------------------------------------------------------------------------------------------------------

Интересный вопрос.. а как сделать так, что когда мы запросим в Unity IMessenger с определенным типом.. например string, то чтобы вернулся не стандратный инстанс класса Messenger, а какойто другой например MessengerString...
Давайте попробуем реализовать это..

создадим класс:

public class MessengerString : IMessenger<string>
{
    public string Message
    {
        get { return "MessengerString"; }
    }
}

и также модифицируем app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" requirePermission="false"/>
	</configSections>
	<unity>
		<typeAliases>
			<typeAlias alias="IMessenger" type="UnityAppBlock.IMessenger, UnityAppBlock"/>
			<typeAlias alias="Messenger" type="UnityAppBlock.Messenger, UnityAppBlock"/>
 
			<typeAlias alias="IMessengerT" type="UnityAppBlock.IMessenger`1, UnityAppBlock"/>
			<typeAlias alias="MessengerT" type="UnityAppBlock.Messenger`1, UnityAppBlock"/>
            
			<typeAlias alias="IMessengerOfString" type="UnityAppBlock.IMessenger`1[[System.String, mscorlib]], UnityAppBlock"/>
			<typeAlias alias="MessengerOfString" type="UnityAppBlock.MessengerString, UnityAppBlock"/>
		</typeAliases>
		<containers>
			<container>
				<types>
					<type type="IMessenger" mapTo="Messenger"/>
                    
					<type type="IMessengerT" mapTo="MessengerT"/>
                    
					<type type="IMessengerOfString" mapTo="MessengerOfString"/>
				</types>
			</container>
		</containers>
	</unity>
</configuration>

как видите, чтобы обьявить тип в generic класса, нужно его написать в двойных квадратных скобкаx [[Namespace.Class, Assambly]], после `1

ф-цию Main оставим без изменений... и в результате при запуске мы получим следующие:

Just messenger

-- Generic --
Messenger<Int32>
Messenger<Double>
MessengerString

как видим вместо Messenger создался обьект MessengerString.

--------------------------------------------------------------------------------------------------------


Расмотрим пример, когда generic класс состоит из двух типов:

public interface IMessenger<T, T2> : IMessenger
{
}

public class DoubleMessenger<T, T2> : IMessenger<T, T2>
{
	public string Message
  	{
  		get { return String.Format("DoubleMessenger<{0}, {1}>", typeof(T).Name, typeof(T2).Name); }
  	}
}

app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
  		<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" requirePermission="false"/>
  	</configSections>
	<unity>
  		<typeAliases>
	  		<typeAlias alias="IMessenger" type="UnityAppBlock.IMessenger, UnityAppBlock"/>
	  		<typeAlias alias="Messenger" type="UnityAppBlock.Messenger, UnityAppBlock"/>
        
			<typeAlias alias="IMessengerT" type="UnityAppBlock.IMessenger`1, UnityAppBlock"/>
	  		<typeAlias alias="MessengerT" type="UnityAppBlock.Messenger`1, UnityAppBlock"/>
        
			<typeAlias alias="IMessengerOfString" type="UnityAppBlock.IMessenger`1[[System.String, mscorlib]], UnityAppBlock"/>
  			<typeAlias alias="MessengerOfString" type="UnityAppBlock.MessengerString, UnityAppBlock"/>
        
			<typeAlias alias="IMessengerDoubleT" type="UnityAppBlock.IMessenger`2, UnityAppBlock"/>
			<typeAlias alias="MessengerDoubleT" type="UnityAppBlock.DoubleMessenger`2, UnityAppBlock"/>
		</typeAliases>
  		<containers>
  			<container>
  				<types>
					<type type="IMessenger" mapTo="Messenger"/>
                    
					<type type="IMessengerT" mapTo="MessengerT"/>
                    
					<type type="IMessengerOfString" mapTo="MessengerOfString"/>
                    
					<type type="IMessengerDoubleT" mapTo="MessengerDoubleT"/>
				</types>
			</container>
		</containers>
	</unity>
</configuration>

Main:

static void Main(string[] args)
{
	IUnityContainer container = new UnityContainer();
	var section =
  		(UnityConfigurationSection)ConfigurationManager.GetSection("unity");
        
	section.Containers.Default.Configure(container);
    
	IMessenger messenger = container.Resolve<IMessenger>();    
  	Console.WriteLine(messenger.Message);
    
	Console.WriteLine("\n-- Generic --");
    
	messenger = container.Resolve<IMessenger<int>>() as IMessenger;    
	Console.WriteLine(messenger.Message);
    
	messenger = container.Resolve<IMessenger<double>>() as IMessenger;    
  	Console.WriteLine(messenger.Message);
    
	messenger = container.Resolve<IMessenger<string>>() as IMessenger;    
  	Console.WriteLine(messenger.Message);
    
	Console.WriteLine("\n-- Double Generic --");
    
	messenger = container.Resolve<IMessenger<int, string>>() as IMessenger;
	Console.WriteLine(messenger.Message);
    
	messenger = container.Resolve<IMessenger<DateTime, Guid>>() as IMessenger;
	Console.WriteLine(messenger.Message);
    
	Console.ReadLine();
}

Output будет:

Just messenger

-- Generic --
Messenger<Int32>
Messenger<Double>
MessengerString
-- Double Generic --
DoubleMessenger
DoubleMessenger

--------------------------------------------------------------------------------------------------------

Дальше попробуем сделать, чтобы при запросе типа IMessenger возвращался обьект класса GuidLongMessenger:

public class GuidLongMessenger : IMessenger<Guid, long>
{
    public string Message
    {
        get { return "GuidLongMessenger"; }
    }
}

в app.config добавим:

<typeAlias alias="IMessengerGuidLong" type="UnityAppBlock.IMessenger`2[[System.Guid, mscorlib], [System.Int64, mscorlib]], UnityAppBlock"/>
<typeAlias alias="MessengerGuidLong" type="UnityAppBlock.GuidLongMessenger, UnityAppBlock"/>

<type type="IMessengerGuidLong" mapTo="MessengerGuidLong"/>

Main:

messenger = container.Resolve<IMessenger<Guid, long>>() as IMessenger;
Console.WriteLine(messenger.Message);

Output:

Just messenger

-- Generic --
Messenger<Int32>
Messenger<Double>
<strong>MessengerString</strong>

-- Double Generic --
DoubleMessenger<Int32, String>
DoubleMessenger<DateTime, Guid>
GuidLongMessenger

--------------------------------------------------------------------------------------------------------

Вот и все.. мы научились определять generic типы в xml файле для Unity (сам я потратил причный отрезок времени на поиск решения этой проблемы.. надеюсь мне удалось сохранить ваше))))

WBR,
Bobasoft

Компании из статьи


Microsoft Украина


Сайт:
http://www.microsoft.com/ukr/ua/

Microsoft Украина Украинское подразделение компании Microsoft.

Ищите нас в интернетах!

Комментарии

Свежие вакансии