通过类似GetComponent从组件中直接获得接口的三种方式

2016年10月31日 14:06 0 点赞 0 评论 更新于 2025-11-21 20:44

在开发过程中,我们常常需要实现类似于 GetComponents 等函数的功能,从组件中获取特定的接口。下面将详细介绍三种实现该功能的方式。

方式一:使用抽象类替代接口

此方法不使用接口,而是采用继承自 MonoBehaviour 的抽象类。示例代码如下:

public abstract class LayerPanelBase : MonoBehaviour
{
public abstract void InitView(HeroModel heroModel, CharacterAttributeView characterAttributeView);
}

在使用时,通过 GetComponent<LayerPanelBase>() 方法获取该抽象类的实例,并调用其 InitView 方法,示例代码如下:

GetComponent<LayerPanelBase>().InitView(myHeroModel, this);

这种方式利用抽象类的特性,强制子类实现特定的方法,从而达到类似于接口的效果。

方式二:自定义扩展方法获取接口

该方式的原理与常见的获取组件方法类似,我们可以通过自定义扩展方法来实现从 GameObject 中获取接口。示例代码如下:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

public static class GameObjectEx
{
// 获取单个接口
public static T GetInterface<T>(this GameObject inObj) where T : class
{
if (!typeof(T).IsInterface)
{
Debug.LogError(typeof(T).ToString() + ": is not an actual interface!");
return null;
}
var tmps = inObj.GetComponents<Component>().OfType<T>();
if (tmps.Count() == 0)
return null;
return tmps.First();
}

// 获取多个接口
public static IEnumerable<T> GetInterfaces<T>(this GameObject inObj) where T : class
{
if (!typeof(T).IsInterface)
{
Debug.LogError(typeof(T).ToString() + ": is not an actual interface!");
return Enumerable.Empty<T>();
}
return inObj.GetComponents<Component>().OfType<T>();
}
}

在上述代码中,GetInterface<T> 方法用于获取单个接口实例,GetInterfaces<T> 方法用于获取多个接口实例。这种方式在定义时直接使用接口,是比较推荐的做法,因为它能更清晰地表达代码的意图,并且具有较好的可维护性。

方式三:使用 Linq 查询获取接口

这种方式使用 Linq 查询来筛选出实现了特定接口的组件。示例代码如下:

var controllers = GetComponents<MonoBehaviour>()
.Where(item => item is IInfiniteScrollSetup)
.Select(item => item as IInfiniteScrollSetup)
.ToList();

我们还可以将其封装成扩展方法,方便在其他地方使用:

public static List<T> GetInterfaces<T>(this GameObject obj) where T : class
{
return obj.GetComponents<MonoBehaviour>()
.Where(item => item is T)
.Select(item => item as T)
.ToList();
}

不过,这种方式没办法提供类似于 GetComponent 那样只获取一个接口实例的方法。因此,相对而言,第二种方式更加灵活,既可以获取单个接口实例(GetInterface),也可以获取多个接口实例(GetInterfaces)。

综上所述,在实际开发中,我们可以根据具体的需求选择合适的方式来从组件中获取接口。如果需要更清晰的代码结构和更好的可维护性,推荐使用第二种方式;如果只是简单地筛选实现特定接口的组件,第三种方式也是一个不错的选择;而第一种方式则适用于需要使用抽象类特性的场景。

作者信息

孟子菇凉

孟子菇凉

共发布了 3994 篇文章