将类型为Object的对象转换为匿名类型。

14 浏览
0 Comments

将类型为Object的对象转换为匿名类型。

我正在尝试在.NET 4.0中利用System.Runtime.Caching.MemoryCache类。我有一个通用方法,可以将任何类型传递到内存缓存中,并在调用时获取回来。\n该方法返回一个对象,类型为object,其中包含缓存对象的字段Value。\n我的问题是,我如何将获取到的对象强制转换为其对应的类型?\n以下是我的代码...\n

public static class ObjectCache
{
    private static MemoryCache _cache = new MemoryCache("GetAllMakes");
    public static object GetItem(string key)
    {
        return AddOrGetExisting(key, () => InitialiseItem(key));
    }
    private static T AddOrGetExisting(string key, Func valueFactory)
    {
        var newValue = new Lazy(valueFactory);
        var oldValue = _cache.AddOrGetExisting(key, newValue, new CacheItemPolicy()) as Lazy;
        try
        {
            return (oldValue ?? newValue).Value;
        }
        catch
        {
            _cache.Remove(key);
            throw;
        }
    }
    /// 
    /// 如何访问Value并将其强制转换为类型 "List"
    /// 
    /// 
    /// 
    private static object InitialiseItem(string key)
    {
        // SearchVehicleData.GetAllMakes(false) 的类型是 List
        return new { Value = SearchVehicleData.GetAllMakes(false) };
    }
}

\n以及单元测试...\n

[TestMethod]
public void TestGetAllMakes_Cached()
{
    dynamic ReturnObj = ObjectCache.GetItem("GetAllMakes");
    // *********************************************
    // 由于测试者的类型是Object且没有Value字段,所以无法这样做
    foreach(IBrowseStockVehicle item in ReturnObj.Value)
    {
    }
}

0
0 Comments

在使用缓存时,我们需要将对象存储到缓存中并在需要时从缓存中获取。在这个过程中,可能会遇到将匿名类型从对象类型转换的问题。下面我们来看一下这个问题出现的原因以及解决方法。

在上述代码中,我们可以看到一个名为Cache的实用类,它使用了HttpRuntime.Cache来存储和获取缓存对象。在这个类中,有一个Get方法用于从缓存中获取对象,并将其转换为指定的类型T。这里使用了对象类型Object来存储缓存对象,而不是使用泛型来指定类型。

然而,在进行类型转换时,可能会遇到将匿名类型从对象类型转换的问题。在代码中,我们可以看到在转换之前,使用了is关键字来检查对象是否属于类型T。如果不属于,就会返回false,并返回默认值。这就是出现问题的地方。

为了解决这个问题,我们可以使用泛型来指定类型T,而不是使用对象类型Object。这样,我们就可以避免将匿名类型从对象类型转换的问题。同时,我们还可以在获取缓存对象时使用泛型方法来指定类型T,以避免在代码中进行类型转换。

下面是修改后的Cache类的代码:

namespace Xyz.WebLibrary
{
    public static class Cache
    {
        // Get the value from the HttpRuntime.Cache that was stored using the cacheKey (if any). Returns true if a matching object of requested type T was found in the cache. Otherwise false is returned, along with a default(T) object or value.
        public static bool Get(string cacheKey, out T result)
        {
            if (!string.IsNullOrEmpty(cacheKey))
            {
                object o = HttpRuntime.Cache.Get(cacheKey);
                if (o != null && o is T)
                {
                    result = (T)o;
                    return true;
                }
            }
            result = default(T);
            return false;
        }
        // Store a value in the HttpRuntime.Cache using the cacheKey and the specified expiration time in minutes.
        public static void Set(string cacheKey, T o, int slidingMinutes)
        {
            if (!string.IsNullOrEmpty(cacheKey) && slidingMinutes > 0)
                HttpRuntime.Cache.Insert(cacheKey, o, null, DateTime.MaxValue, TimeSpan.FromMinutes(slidingMinutes), CacheItemPriority.Normal, null);
        }
        // Erase the value from the HttpRuntime.Cache that was stored using the cacheKey (if any).
        public static void Erase(string cacheKey)
        {
            if (!string.IsNullOrEmpty(cacheKey) && HttpRuntime.Cache.Get(cacheKey) != null)
                HttpRuntime.Cache.Remove(cacheKey);
        }
    }
}

上述代码中,我们将Get方法和Set方法改为了泛型方法,使用泛型来指定类型T。这样,我们就可以在使用Cache类时,指定需要获取的对象的类型。例如,我们可以使用以下代码来从缓存中获取ProductInfo类型的对象:

ProductInfo p;
int id = 12345;
string key = "ProductInfo_" + id;
if (!Cache.Get(key, out p))
{
    p = GetProductInfoFromDB(id);
    Cache.Set(key, p, slidingMinutes: 5);
}

在上述代码中,我们首先尝试从缓存中获取ProductInfo类型的对象。如果获取失败,则从数据库中获取对象,并将其存储到缓存中。这样,我们就避免了将匿名类型从对象类型转换的问题,并且可以更方便地使用缓存功能。

,将匿名类型从对象类型转换的问题可以通过使用泛型来解决。通过将获取缓存对象的方法改为泛型方法,并在使用缓存时指定对象的类型,我们可以避免类型转换的问题,并更方便地使用缓存功能。

0
0 Comments

从上述内容中可以整理出以下问题的出现原因和解决方法:

问题:如何将获取到的对象转换为对应的类型?

原因:无法进行此操作!匿名类型在高层次/语义层面上是匿名的(即你不能转换为未知类型,对吧?),并且在低层次上是不可访问且具有随机名称的。也就是说,它们是不可访问的。

解决方法:

1. 将整个对象转换为字典,并使用键访问其属性。可以参考之前的一些回答,这些回答对于像你这样的简单情况可能很有用:将对象映射为字典以及如何将类转换为Dictionary

2. 使用动态对象。

动态对象的解决方法如下:

public sealed class DynamicWrapper : DynamicObject
{
    public DynamicWrapper(object target)
    {
        Target = target;
        // 我们将属性名称和属性元数据存储在字典中,以便后续加速(我们可以使用时间复杂度O(1)查找是否存在所请求的属性!)
        TargetProperties = target.GetType()
                                .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                                .ToDictionary(p => p.Name, p => p);
    }
    
    private IDictionary TargetProperties { get; }
    private object Target { get; }
    
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        // 不支持设置属性!
        throw new NotSupportedException();
    }
    
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        PropertyInfo property;
        if(TargetProperties.TryGetValue(binder.Name, out property))
        {
            result = property.GetValue(Target); 
            return true;
        }
        else
        {
            result = null;
            return false;
        }
    }
}

使用整个包装器的示例如下:

var obj = new { Text = "hello world" };
dynamic dynObj = new DynamicWrapper(obj);
string text = dynObj.Text;

结论:

- 将缓存的对象存储并检索封装在类似于`DynamicWrapper`的东西中,它将按照你的预期工作!

- 或者使用字典。

- 或者,正如其他回答者已经提到的,不要使用匿名类型,而是存储具体类型。

0
0 Comments

在这个问题中,无法将类型为Object的对象强制转换为匿名类型(Casting anonymous type from type Object)。匿名类型是没有类型名称的,因此无法直接进行类型转换。

然而,仍然可以使用反射来实现该功能,但在这种情况下,这可能不是一个真正可用的解决方法。下面是一个示例代码:

var x = ReturnObj.GetType().GetProperty("Value").GetValue(ReturnObj);

在这个示例中,`ReturnObj`是一个类型为Object的对象。通过使用反射,我们可以使用`GetType()`方法获取其实际类型,然后使用`GetProperty()`方法获取名为"Value"的属性,最后使用`GetValue()`方法获取该属性的值。这样我们就可以得到一个类型为Object的对象,但是无法直接将其转换为匿名类型。

然而,使用反射来处理这个问题可能会导致代码变得复杂和难以维护。如果可能的话,建议考虑使用其他方法来解决类型转换的问题,例如使用具有已知类型的对象,或者通过修改代码结构来避免需要进行此类型转换的情况。

0