powered by simpleCommunicator - 2.0.59     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Как получить тип?
9 сообщений из 9, страница 1 из 1
Как получить тип?
    #39107297
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте!
Есть следующие типы:
Код: c#
1.
2.
3.
4.
class Model1 : IModel
{
public ModelIds ModelId => ModelIds.Article;
}



ModelIds - это enum

Вопрос такой: System.Type type = function(x), где function(x) - это функция поиска типа по переданному значению x, где х - одно из значений перечисления ModelIds.

Предполагается следующее использование:
Код: c#
1.
Repository.IncrementView(Repository.FindAsync<type>(id))



Спасибо.
...
Рейтинг: 0 / 0
Как получить тип?
    #39107298
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ДА! и искомый тип должен реализовывать интерфейс IModel
...
Рейтинг: 0 / 0
Как получить тип?
    #39107332
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunter,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public class MyController : Controller
{
   private Func<ModelIds, IModel> _modelFactory;

   public MyController(Func<ModelIds, IModel> modelFactory)
   {
       _modelFactory = modelFactory;
   }

   public ActionResult Some(ModelIds id)
   {
       var model = _modelFactory(id);
   }
}



Регистрация типов (на примере Autofac):

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
var builder = new ContainerBuilder();

builder
   .RegisterType<ModelOne>()
   .Keyed<IModel>(ModelIds.One);

builder
   .RegisterType<ModelSecond>()
   .Keyed<IModel>(ModelIds.Second);



усё.

т.е. не надо морочиться с резолвом типа, ты можешь получать сразу инстанс нужного типа и регистрировать как именно этот инстанс должен быть создан (любой, сколь угодно сложный алгоритм).
...
Рейтинг: 0 / 0
Как получить тип?
    #39107360
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Да инстанс конечно получили. Но ведь как показано тут Repository.FindAsync<type>(id) - нужен не инстанс а сущьность. Функция Repository.IncrementView принимает сущность EF и далее с ней работает.
Код: 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 EntityView IncrementView<T>(T model) where T : class, IView
        {
            if (model != null)
            {
                try
                {
                    model.TotalView += 1;
                    Context.Set<T>();
                    Context.SaveChanges();
                }
                catch (Exception)
                {
                    // ignored
                }

                var er = new EntityView(model.ModelId)
                {
                    Id = model.Id,
                    TotalView = model.TotalView
                };

                return er;
            }
            return new EntityView(ModelIds.NullModel);
        }
...
Рейтинг: 0 / 0
Как получить тип?
    #39107391
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
сейчас реализовано вот так (не очень хорошо) - нет универсальности.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
public ActionResult View(FormCollection form)
        {

            int id = Convert.ToInt32(form["Id"]);
            ModelIds modelId = (ModelIds)Enum.Parse(typeof(ModelIds), form["modelId"]);

            EntityView ev = new EntityView(modelId);

            switch (modelId)
            {
                case ModelIds.Article:
                    ev = Repository.IncrementView(Repository.Find<Article>(id));
                    break;
                case ModelIds.News:
                    ev = Repository.IncrementView(Repository.Find<News>(id));
                    break;
            }

            return Json(new { result = string.Format("{0}", Message), success = true, ev }, JsonRequestBehavior.AllowGet);
        }



т.е. нужно избавитьс от свича
...
Рейтинг: 0 / 0
Как получить тип?
    #39107423
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunterт.е. нужно избавитьс от свича

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public enum ModelIds
{
    [ModelType(typeof(SomeModelOne))]
    One,

    [ModelType(typeof(SomeModelOne))]
    Two,

    [ModelType(typeof(SomeModelOne))]
    Three

}



тебе нужно реализовать кастомный атрибут ModelTypeAttribute, в который можно передать тип.

затем, имея на руках значение ModelIds, можно через рефлекшен получить вышеуказанный атрибут и извлечь тип.

усё. никаких кейсов, никаких словарей и регистраций. типы пробиваешь прямо атрибутами вместе с енумами..
...
Рейтинг: 0 / 0
Как получить тип?
    #39107742
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
public static class EnumHelper
    {
        public static T GetAttributeOfType<T>(this Enum enumVal) where T : Attribute
        {
            var type = enumVal.GetType();
            var memInfo = type.GetMember(enumVal.ToString());
            var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
            return (attributes.Length > 0) ? (T)attributes[0] : null;
        }
    }
}

Type type = modelId.GetAttributeOfType<ModelTypeAttribute>().ModelType;

ModelIds modelId = (ModelIds)Enum.Parse(typeof(ModelIds), form["modelId"]);

EntityView ev = new EntityView(modelId);

Type type = modelId.GetAttributeOfType<ModelTypeAttribute>().ModelType;

ev = await Repository.IncrementView(Repository.FindAsync<type>(id).Result);



-- злится (( что не так делаю?
...
Рейтинг: 0 / 0
Как получить тип?
    #39108264
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ughunter
Код: c#
1.
ev = await Repository.IncrementView(Repository.FindAsync<type>(id).Result);



Так нельзя передавать тип. В угловых скобках можно передавать только известный на этапе компиляции тип, а в рантайме нельзя.

Тут либо надо через рефлекшен сконструировать метод FindAsync параметризированный типом:

Код: c#
1.
2.
3.
4.
var task = Repository.GetType()
	.GetMethod("FindAsync")
	.MakeGenericMethod(type)
	.Invoke(Repository, new object[] { id });



, либо использовать другой метод репозитория, который принимает одним из параметров тип:

Repository.FindAsync(type, id)
...
Рейтинг: 0 / 0
Как получить тип?
    #39108950
ughunter
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt, спасибо огромное - ты просто гений!

в конце дополню - если кто наткнется на топик ))

Код: c#
1.
2.
3.
4.
5.
6.
dynamic task = Repository.GetType().GetMethod("FindAsync").MakeGenericMethod(type).Invoke(Repository, new object[] { id });
var result = await task;

ev = await Repository.IncrementView(result as Domain.Abstract.IView);

return Json(new { result = string.Format("{0}", Message), success = true, ev }, JsonRequestBehavior.AllowGet);



в IncrementView проверка на null - и все взлетело )
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Как получить тип?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]