我想访问我的log::Log个Impl实例以访问特定的字段,但一旦我收到引用,我就不能将其向下转换到我的 struct 中.

我试图将记录器引用转换为core::any::Any,然后将其向下转换为我的原始 struct ,但我总是得到None.

use core::any::Any;

pub trait AToAny: 'static {
    fn as_any(&self) -> &dyn Any;
}

impl<T: 'static> AToAny for T {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

struct MyLogger {}

impl log::Log for MyLogger {
    fn enabled(&self, _: &log::Metadata<'_>) -> bool { todo!() }
    fn log(&self, _: &log::Record<'_>) { todo!() }
    fn flush(&self) { todo!() }
}

pub fn main() {
    let logger_impl = MyLogger {};
    log::set_boxed_logger(Box::new(logger_impl)).unwrap();
    let logger = log::logger();
    
    let logger_any = logger.as_any();
    let logger_impl = logger_any.downcast_ref::<MyLogger>()
        .expect("downcast failed");
}

我也try 了,但没有通过日志(log)初始化函数,但我得到了相同的结果:

use core::any::Any; // 0.10.1

pub trait AToAny: 'static {
    fn as_any(&self) -> &dyn Any;
}

impl<T: 'static> AToAny for T {
    fn as_any(&self) -> &dyn Any {
        self
    }
}

struct MyLogger {}

impl log::Log for MyLogger {
    fn enabled(&self, _: &log::Metadata<'_>) -> bool { todo!() }
    fn log(&self, _: &log::Record<'_>) { todo!() }
    fn flush(&self) { todo!() }
}

pub fn main() {
    let logger_impl = MyLogger {};
    let logger_boxed: Box<MyLogger> = Box::new(logger_impl);
    let logger: &'static mut dyn log::Log = Box::leak(logger_boxed);
    
    let logger_any = logger.as_any();
    let logger_impl = logger_any.downcast_ref::<MyLogger>()
        .expect("downcast failed");
}

这是code on the playground美元.

我看到logger变量中的type_idlogger_impl中的type_id不同,所以我相信这就是阻止我进行向下预测的原因,但我不能理解我应该如何修复这个问题.

推荐答案

你正在调用<&dyn Log>::as_any,但你只能将其降低到&dyn Log,也就是logger_any.downcast_ref::<&dyn log::Log>()返回Some,但它不会给你带来任何结果.A&dyn Log没有将必要的信息下传到MyLogger.

幸运的是,您在这里根本不需要Any或向下转换,因为您可以只使用共享引用设置gobal记录器,并且仍然可以访问记录器本身,因为共享引用实现Copy:

struct MyLogger {
    bar: &'static str,
}
impl MyLogger {
    fn foo(&self) {
        println!("foo")
    }
}
pub fn main() {
    let logger: &MyLogger = Box::leak(Box::new(MyLogger { bar: "baz"}));
    log::set_logger(logger as &dyn log::Log).unwrap(); // the cast is not needed, but illustrates what's happening implicitly otherwise.
    logger.foo(); // can still call inherent MyLogger::foo
    println!("{}", logger.bar); // and access fields.
}

Rust相关问答推荐

如何找到一个数字在二维数组中的位置(S)?

如何在Rust中实现Functor trait?

使用 struct 外部的属性来改变 struct 的原始方式

编译项目期间使用Cargo生成时出现rustc错误

使用Py03从Rust调用Python函数时的最佳返回类型

避免在Collect()上进行涡鱼类型的涂抹,以产生<;Vec<;_>;,_>;

变量需要parse()中的显式类型

如何使用tracing-subscriberRust crate 构建多编写者、全局过滤订阅者

将多维数组转换为切片

Rust typestate 模式:实现多个状态?

在给定 Rust 谓词的情况下,将 Some 转换为 None 的惯用方法是什么?

Rust:`sort_by` 多个条件,冗长的模式匹配

从嵌入式 Rust 中的某个时刻开始经过的时间

当你删除一个存在于堆栈中的值时,为什么 rust 不会抱怨

判断对象是 PyDatetime 还是 Pydate 的实例?

为什么分配对变量的引用使我无法返回它

Iterator::collect如何进行转换?

类型组的通用枚举

在 Rust 中有条件地导入?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?