Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139

Cast interface to concrete type

27.09.2017, 14:32. Показов 1714. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день. Имеется агрегатор событий , у которого "издатели и подписчики" реализуют интерфейс "IApplicationEvent". Понадобилось держать список таких событий в какой-нибудь коллекции ,у которой тип элементов соответственно "IApplicationEvent". При публикации события агрегатор использует тип события для его поиска в словаре подписок. Есть две реализации "EatFruit" , "ClimbToRock" интерфейса. При переборе коллекции происходит публикация этого события, но так как тип переменной будет "IApplicationEvent" , то ничего не произойдет так,как такого типа нет в подписках (есть "EatFruit" , "ClimbToRock"). Возможно ли без кучи свичей прикастовать интерфейс к конкретному типу или же нужно переписать логику агрегатора?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.09.2017, 14:32
Ответы с готовыми решениями:

Ошибка CDO:Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.Office.Interop.Outlook.MailItem'
Здаствуйте у меня такая проблема, я получаю сообщения с Outlook'а путем простейших махинаций, когда запускаю цикл для сохранения имени...

Cannot implicitly convert type 'int' to 'int*'. An explicit conversion exists (are you missing a cast?)
Собственно вот код: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace...

'type cast' из DWORD в набор бит
например если есть функция принимающая DWORD ... не хотелось-бы каждый раз при вызове добавлять к списку ещё и приведение, типа ...

8
.NET C#,ASP.NET MVC
Эксперт .NET
 Аватар для lvlkoo
594 / 507 / 224
Регистрация: 16.10.2010
Сообщений: 1,902
27.09.2017, 15:58
Перепилывайте логику EatFruit и ClimbToRock так, чтобы вам не нужно было использовать конвретный тип, выделите общую логику и засунте в интерфейс.

C#
1
2
3
4
5
IApplicationEvent fruit = new EatFruit();
IApplicationEvent climb = new ClimbToRock();
 
EatFruit casted1 = (EatFruit) fruit; //ошибки не будет
ClimbToRock casted2 = (ClimbToRock) fruit; //будет ошибка во время выполнения
так что или свичи или переделывайте дабы выделить общую логику
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
27.09.2017, 16:46  [ТС]
lvlkoo, Вы ,наверное, не так поняли меня. Логики в этом интерфейсе вообще нет и не предполагалась. Я уж не такой нубас и знаю о том ,что схвачу runtime error.
Имеем словарь в агрегаторе.
C#
1
private readonly ConcurrentDictionary<Type, IList> _subscriptions = new ConcurrentDictionary<Type, IList>();
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 public async Task PublishAsync<TMessage>(TMessage message) where TMessage : IApplicationEvent
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
           //Получаю тут IApplicationEvent, а хотелось бы конкретный класс.
            var messageType = typeof(TMessage);
            List<ISubscription<TMessage>> subscriptionList = null;
            lock (_lock)
            {
                if (_subscriptions.ContainsKey(messageType))
                {
                    subscriptionList = new List<ISubscription<TMessage>>(
                        _subscriptions[messageType].Cast<ISubscription<TMessage>>());
                }
            }
            if (subscriptionList != null)
            {
                foreach (var subscription in subscriptionList)
                {
                    await subscription.Action(message);
                }
            }
        }
Создаю список событий
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 public class RealService : IZipEventService
        {
            Random random = new Random();  
            public async Task<ICollection<IApplicationEvent>> GetZipEventsAsync(string NamePartionAction)
            {
                // fake some latency or similiar
                await Task.Delay(random.Next(10) + 10);
                // calculate two "zip codes". First: sum of all letters, Second: first letter only
                //var zip1 = cityName.Select(_ => _).Sum(_ => (int)_);
                //var zip2 = (int)cityName.First();
               var task =   Task.Factory.StartNew( () =>
                {
                    return  new List<IApplicationEvent>() {
                        new ClimbToRockNow(), new EatBananaNow(),
                       new ClimbToRockNow(), new ClimbToRockNow(), new EatBananaNow()
                    };
                });
                return await task;
            }
        }
C#
1
2
3
4
5
6
result = await cache1.GetZipEventsAsync("One");
            foreach(var item in result)
            {
                //Соответственно тут item это IApplicationEvent.
                await eventAggregator.PublishAsync(item);
            }


Получается остаются только свичи или изменение типа...(но на какой) в словаре?
0
 Аватар для Cupko
658 / 595 / 171
Регистрация: 17.07.2012
Сообщений: 1,682
Записей в блоге: 1
27.09.2017, 17:20
А GetType() у инстанса получать пробовали?
1
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
27.09.2017, 17:45  [ТС]
Cupko, пробовал) InvalidCastException вываливается при касте.
C#
1
2
3
4
5
6
7
8
9
10
var messageType = message.GetType();
            List<ISubscription<TMessage>> subscriptionList = null;
            lock (_lock)
            {
                if (_subscriptions.ContainsKey(messageType))
                {
                    subscriptionList = new List<ISubscription<TMessage>>(
                        _subscriptions[messageType].Cast<ISubscription<TMessage>>());
                }
            }
0
.NET C#,ASP.NET MVC
Эксперт .NET
 Аватар для lvlkoo
594 / 507 / 224
Регистрация: 16.10.2010
Сообщений: 1,902
27.09.2017, 18:20
Jexio, так вопрос уже не в том что там не тот ключ?
Что в дебагере? в messageType вы правильный тип получили?

Цитата Сообщение от Jexio Посмотреть сообщение
ConcurrentDictionary<Type, IList>
Цитата Сообщение от Jexio Посмотреть сообщение
_subscriptions[messageType].Cast<ISubscription<TMessage>>()

ISubscription<TMessage> реализует IEnumerable<TMessage>?
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
27.09.2017, 18:42  [ТС]
lvlkoo, Дело в том ,что typeof и GetType работают по-разному. typeof - получает имя типа на этапе компиляции. GetType - тип экземпляра. Соответственно
C#
1
message.GetType()  != typeof(TMessage)
Не совсем понял для какой цели ISubscription<TMessage> реализовать IEnumerable<TMessage>

Вот сведения об ошибке.
Не удалось привести тип объекта "ProjectZoo.Backend.EvtJunction.Aggregat or.Subscription`1[ProjectZoo.Form1+ClimbToRockNow]" к типу "ProjectZoo.Backend.EvtJunction.Aggregat or.ISubscription`1[ProjectZoo.Backend.EvtJunction.Aggregato r.IApplicationEvent]".

C#
1
2
3
4
5
6
7
8
9
10
 public interface ISubscription<TMessage> : IDisposable, IEquatable<ISubscription<TMessage>> where TMessage : IApplicationEvent
    {
        Guid SubscriptionId { get; }
 
        Func<TMessage, Task> Action { get; }
 
        IEventAggregator EventAggregator { get; }
 
        Guid CorrelationId { get; set; }
    }
Добавлено через 7 минут
lvlkoo, При использование typeof(TMessage) каставалось без ошибок.. может я чего-то не понимаю..
0
.NET C#,ASP.NET MVC
Эксперт .NET
 Аватар для lvlkoo
594 / 507 / 224
Регистрация: 16.10.2010
Сообщений: 1,902
27.09.2017, 19:01
Цитата Сообщение от Jexio Посмотреть сообщение
- получает имя типа
typeof() возвращает обьект System.Type на основе передаваемого ему ТИПА, а .GetType() возвращает тот же System.Type но на основе типа инстанса.

Цитата Сообщение от Jexio Посмотреть сообщение
message.GetType() *!= typeof(TMessage)
Понятное дело.

Цитата Сообщение от Jexio Посмотреть сообщение
public async Task PublishAsync<TMessage>(TMessage message) where TMessage : IApplicationEvent
C#
1
var type = typeof(TMessage) //IApplicationEvent

C#
1
var type = message.GetType() //тип конкретного обьекта message
Цитата Сообщение от Jexio Посмотреть сообщение
Не совсем понял для какой цели ISubscription<TMessage> реализовать IEnumerable<TMessage>
Сори, тут немного код не досмотрел с кастом.

Цитата Сообщение от Jexio Посмотреть сообщение
Не удалось привести тип объекта "ProjectZoo.Backend.EvtJunction.Aggregat or.Subscription`1[ProjectZoo.Form1+ClimbToRockNow]" к типу "ProjectZoo.Backend.EvtJunction.Aggregat or.ISubscription`1[ProjectZoo.Backend.EvtJunction.Aggregato r.IApplicationEvent]".
Разные типы же.

Покажите пример заполнения словаря, и что за Subscription?
0
1 / 1 / 1
Регистрация: 22.11.2015
Сообщений: 139
27.09.2017, 19:13  [ТС]
lvlkoo, Вот реализация ISubscription
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
 public class Subscription<TMessage> : ISubscription<TMessage> where TMessage : IApplicationEvent
    {
        private bool _disposed;
        private Guid _subscriptionId;
 
        public Subscription(IEventAggregator eventAggregator, Func<TMessage, Task> action, Guid correlationId = default(Guid))
        {
            EventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
            Action = action ?? throw new ArgumentNullException(nameof(action));
            CorrelationId = correlationId == default(Guid) ? Guid.NewGuid() : correlationId;
        }
 
        public Guid SubscriptionId
        {
            get
            {
                if (_subscriptionId == Guid.Empty)
                    _subscriptionId = Guid.NewGuid();
                return _subscriptionId;
            }
        }
 
        public Guid CorrelationId { get; set; }
 
        public Func<TMessage, Task> Action { get; private set; }
 
        public IEventAggregator EventAggregator { get; private set; }
 
        #region -- Dispose Implementation --
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        protected virtual void Dispose(bool disposing)
        {
            if (_disposed)
                return;
            if (!disposing)
                return;
            EventAggregator.UnSubscribe(this);
            _disposed = true;
        }
        #endregion
 
        #region -- Equality Implementation --
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != GetType())
                return false;
            return Equals((Subscription<TMessage>)obj);
        }
 
        public bool Equals(ISubscription<TMessage> other)
        {
            if (ReferenceEquals(null, other))
                return false;
            if (ReferenceEquals(this, other))
                return true;
            return _subscriptionId.Equals(other.SubscriptionId);
        }
 
        public override int GetHashCode() { return SubscriptionId.GetHashCode(); }
 
        public IEnumerator<TMessage> GetEnumerator()
        {
            throw new NotImplementedException();
        }
 
        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
 
        public static bool operator ==(Subscription<TMessage> left, Subscription<TMessage> right) { return Equals(left, right); }
 
        public static bool operator !=(Subscription<TMessage> left, Subscription<TMessage> right) { return !Equals(left, right); }
        #endregion
    }


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  _action = new List<IAction>() { new EatBananaAction(), new ProxyClimbToRock() { ClimbHeight = 27 } };
 eventAggregator = new EventAggregator();
 monkey = new Monkey(_action) { Age = 10 };
Func<ClimbToRockNow, Task> _rockFront = message =>
            {
               return Task.Factory.StartNew(async
                () =>
                {
                    var climb = new ProxyClimbToRock() { ClimbHeight = 24 };
                    var actionComplete =  await monkey.MakeAction(climb);
                    return actionComplete;
 
                }).ContinueWith(async t =>
                {
                    var result = await await t;
                    if (result)
                        richTextBox1.AppendText("Climb to rock now" + Environment.NewLine);
                }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, context);
            };
var subscription_second = eventAggregator.Subscribe(_bananFront);
Добавление в словарь
Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
 public ISubscription<T> Subscribe<T>(Func<T, Task> action, Guid correlationId = default(Guid)) where T : IApplicationEvent
        {
            lock (_lock)
            {
                var messageType = typeof(T);
                var subscription = new Subscription<T>(this, action, correlationId);
 
                // Check to see if we have this event message type defined in the subscriptions dictionary. If not, create the
                // event message type and add the subscription to it.
                if (_subscriptions.ContainsKey(messageType))
                {
                    // Check to see if there is already a subscription of the same type with the same correlation ID
                    if (correlationId != default(Guid))
                    {
                        var hasCorrelationID = false;
                        var subsList = _subscriptions[messageType];
 
                        // Iterate through the subscriptions and determine if there is an existing subscription with that correlation ID
                        foreach (Subscription<T> subscriptionItem in subsList)
                        {
                            // We check for a match on both the correlation Id and the action (or method to be called when event is published)
                            hasCorrelationID = subscriptionItem.CorrelationId == correlationId && subscriptionItem.Action == action;
 
                            // If we don't have a correlation Id then we continue with the loop
                            if (!hasCorrelationID)
                            {
                                continue;
                            }
 
                            // Otherwise we we pull the existing subscription out of the current list and return 
                            // that back to the subscriber.
                            subscription = subscriptionItem;
                        }
                        if (!hasCorrelationID)
                        {
                            _subscriptions[messageType].Add(subscription);
                        }
                    }
                    else
                    {
                        _subscriptions[messageType].Add(subscription);
                    }
                }
                else
                {
                    _subscriptions.GetOrAdd(messageType, new List<ISubscription<T>> { subscription });
                }
                return subscription;
            }
        }
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.09.2017, 19:13
Помогаю со студенческими работами здесь

Function or interface marked as restricted, or the function uses an Automation type not supported
Добрый день! Столкнулась с неожиданной проблемой: Объявляю переменные для программы глобально. 'Данные заказчика Dim Name...

Templates. (concrete inheritance). question to destructor implementation
Есть вот такой вот проект. Идея в том том что конкретный класс наследуется от темплейта. Как в таком случае ПРАВИЛЬНО + ГРАМОТНО...

lexical cast
есть шаблонный класс внутри делается каст к инту все это внутри dll template &lt;class T&gt; class A { public: A(T...

Dynamic Cast C++
Прошу объяснить, что я делаю не так.. Есть у меня три класса: Man - базовый, Staff и Student - производные. Виртуализированы. ...

Unchecked cast
Добрый день, Объясните, пожалуйста, как лучше всего обойти ошибку приведения типов. Ситуация такая: для хранения упорядоченного...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru